Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
Introduction
============

TrueRandom generates true random numbers on Arduino. They are different every
time you start your program, and are truly unpredictable unlike the default
Arduino random() function.

Compatibility
=============

TrueRandom currently functions on the Arduino Diecimila, Duemilanove, 168 and
328 based Arduinos and Nordics nRF5 platform. It does not yet function on the
Arduino Mega.

On patforms without a Hardware Random Number Generator, TrueRandom uses Analog 0.
Do not connect anything to this pin. These restrictions may be removed in future
versions of this library.

On Nordiv nRF5 platforms the internal Hardware Number Generator (RNG) is used
for random number generation. The "Bias Correction" is enabled to provide better
random numbers.

Generating a random byte takes a maximum of 250uS with nRF52 series and 677uS
with nRF51 series MCU.

What happens when you use the Arduino random() function?
========================================================

The Arduino default random() function generates what appear to be random
numbers. They are actually calculated from a formula. On reset, the formula
is reset at a start point, then progresses through a long sequence of random
looking numbers. However, Arduino starts at the same point in the sequence
every reset. You can move to a different part of the sequence using srandom(),
but how do you get a random start point from in the first place?

What happens when you use TrueRandom.random() function?
=======================================================

You get a random number. Really random. Different every time you restart.

Example time
============

```C
#include <TrueRandom.h>

void setup() {
Serial.begin(9600);

Serial.print("I threw a random die and got ");
Serial.print(random(1,7));

Serial.print(". Then I threw a TrueRandom die and got ");
Serial.println(TrueRandom.random(1,7));

}

void loop() {
; // Do nothing
}
```

Upload that code to an nRF5 and watch it on the Serial Monitor at 9600 baud.
Hit the reset button, and see what it does. The random() function returns the
same value every time, but the TrueRandom version is always different.

TrueRandom basic functions
==========================

The existing random functions of Arduino are replicated in TrueRandom.

_TrueRandom.random()_
Like the Arduino library and ANSI C, this generates a random number between 0
and the highest signed long integer 2,147,483,647.

_TrueRandom.random(n)_
This generates a random number between 0 and (n-1). So random(6) will generate
numbers between 0 and 5.

_TrueRandom.random(a,b)_
This generates a random number between a and (b-1). So random(1,7) will generate
numbers between 1 and 6.

TrueRandom advanced functions
=============================

_TrueRandom.randomBit()_
Generating true random numbers takes time, so it can be useful to only generate
as many random bits as you need. randomBit() generates a 0 or a 1 with 50%
probability. This is the core function from which the other TrueRandom libraries
are built.

_TrueRandom.randomByte()_
Generates a random byte between 0 and 255. Equivalent to random(256).

_TrueRandom.rand()_
Like the ANSI C rand() command, this generates a random number between 0 and the
highest signed integer 32767.

_TrueRandom.memfill(address, length)_
Fills a block of bytes with random numbers. (length) bytes are filled in total,
starting at the given (address).

TrueRandom specialist functions
===============================

_TrueRandom.mac(address)_
When operating devices on an Ethernet network, each device must have a unique
MAC address. Officially, MAC addresses should be assigned formally via the IEEE
Registration Authority. However, for practical purposes, MAC addresses can be
randomly assigned without problems. This function writes a 6 byte MAC address
to a given address. Randomly generated MAC addresses are great for projects or
workshops involving large numbers of Arduino Ethernet shields, as each shield
has a different MAC address, even though they are running identical code. See
the MacAddress example which shows this in use.

_TrueRandom.uuid(address)_
UUIDs are unique identifiers. They are 16 bytes (128 bits) long, which means
that generating them randomly This generates a random UUID, and writes it to
an array. UUIDs are globally unique numbers that are often used in web services
and production electronics. TrueRandom can produce any one of
5,316,911,983,139,663,491,615,228,241,121,378,304 different numbers. You're more
likely to win top prize in the national lottery 3 times in a row than get two
matching UUIDs.

How TrueRandom works
====================

It is hard to get a truly random number from Arduino. TrueRandom does it by
setting up a noisy voltage on Analog pin 0, measuring it, and then discarding
all but the least significant bit of the measured value. However, that isn't
noisy enough, so a von Neumann whitening algorithm gathers enough entropy from
multiple readings to ensure a fair distribution of 1s and 0s.

The other functions within TrueRandom construct the requested values by
gathering just enough random bits to produce the required numbers. Generating a
random bit takes time, so a significant part of the code works to ensure the
random bits are used as efficiently as possible.

Projects using TrueRandom
=========================

Generative Music from Gijs
83 changes: 78 additions & 5 deletions TrueRandom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,79 @@
* Copyright (c) 2010 Peter Knight, Tinker.it! All rights reserved.
*/

#include <avr/io.h>
#include "TrueRandom.h"

#ifdef ARDUINO_ARCH_NRF5
#include <Arduino.h>
/* Support for Nordic nRF5 Platform */
void TrueRandomClass::startRNG(void) {
#ifdef NRF51
NRF_RNG->POWER = 1;
#endif
NRF_RNG->TASKS_START = 1;
NRF_RNG->EVENTS_VALRDY = 0;
}

void TrueRandomClass::stopRNG(void) {
NRF_RNG->TASKS_STOP = 1;
#ifdef NRF51
NRF_RNG->POWER = 0;
#endif
}
char TrueRandomClass::readByte() {
char ret;
while (NRF_RNG->EVENTS_VALRDY == 0) {
yield();
}
ret = (char)NRF_RNG->VALUE;
NRF_RNG->EVENTS_VALRDY = 0;
return ret;
}

int TrueRandomClass::randomBit(void) {
// read a new byte when bitpos is 0
if (this->random_bit_buffer_pos == 0) {
this->random_bit_buffer_pos = 1;
this->random_bit_buffer = this->randomByte();
}

int ret = (this->random_bit_buffer & this->random_bit_buffer_pos) > 0;
this->random_bit_buffer_pos = this->random_bit_buffer_pos << 1;
return (int)ret;
}

char TrueRandomClass::randomByte(void) {
char ret;
this->startRNG();
ret = this->readByte();
this->stopRNG();
return ret;
}

int TrueRandomClass::rand() {
int result;
this->memfill((char*)&result,sizeof(result));
return result;
}

long TrueRandomClass::random() {
long result;
this->memfill((char*)&result,sizeof(result));
return result;
}

void TrueRandomClass::memfill(char* location, int size) {
startRNG();
for (;size--;) {
*location++ = readByte();
}
stopRNG();
}

// End ARDUINO_ARCH_NRF5
#else
/* Support for Arduino Platform */
#include <avr/io.h>
int TrueRandomClass::randomBitRaw(void) {
uint8_t copyAdmux, copyAdcsra, copyAdcsrb, copyPortc, copyDdrc;
uint16_t i;
Expand Down Expand Up @@ -116,6 +186,13 @@ long TrueRandomClass::random() {
return result;
}

void TrueRandomClass::memfill(char* location, int size) {
for (;size--;) *location++ = randomByte();
}

// Arduino platform
#endif

long TrueRandomClass::random(long howBig) {
long randomValue;
long maxRandomValue;
Expand Down Expand Up @@ -166,10 +243,6 @@ long TrueRandomClass::random(long howSmall, long howBig) {
return TrueRandomClass::random(diff) + howSmall;
}

void TrueRandomClass::memfill(char* location, int size) {
for (;size--;) *location++ = randomByte();
}

void TrueRandomClass::mac(uint8_t* macLocation) {
memfill((char*)macLocation,6);
}
Expand Down
10 changes: 9 additions & 1 deletion TrueRandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* TrueRandom - A true random number generator for Arduino.
*
* Copyright (c) 2010 Peter Knight, Tinker.it! All rights reserved.
* Copyright (c) 2016 Frank Holtz, Tinker.it! All rights reserved.
*/

#ifndef TrueRandom_h
Expand All @@ -21,8 +22,15 @@ class TrueRandomClass
void mac(uint8_t* macLocation);
void uuid(uint8_t* uuidLocation);
private:
char random_bit_buffer, random_bit_buffer_pos=0;
#ifdef ARDUINO_ARCH_NRF5
void startRNG(void);
void stopRNG(void);
char readByte();
#else
int randomBitRaw(void);
int randomBitRaw2(void);
#endif
};
extern TrueRandomClass TrueRandom;
#endif
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
char array[10];
int arrayLength = 10;

char macAddress[6]; // MAC addresses are always 6 bytes long
char uuidNumber[16]; // UUIDs are always 16 bytes long
uint8_t macAddress[6]; // MAC addresses are always 6 bytes long
uint8_t uuidNumber[16]; // UUIDs are always 16 bytes long

void printHex(char number) {
// Print high hex digit
Expand All @@ -24,7 +24,7 @@ void printHex(char number) {
Serial.print( "0123456789ABCDEF"[number & 15] );
}

void printMac(char* macAddress) {
void printMac(uint8_t* macAddress) {
// Print a MAC address in the form
// 12:23:34:45:56:67
int i;
Expand All @@ -33,7 +33,7 @@ void printMac(char* macAddress) {
if (i<5) Serial.print(":");
}
}
void printUuid(char* uuidNumber) {
void printUuid(uint8_t* uuidNumber) {
// Print a UUID in the form
// 12345678-1234-1234-1234-123456789ABC
int i;
Expand All @@ -42,7 +42,7 @@ void printUuid(char* uuidNumber) {
if (i==6) Serial.print("-");
if (i==8) Serial.print("-");
if (i==10) Serial.print("-");
printHex(uuid[i]);
printHex(uuidNumber[i]);
}
}

Expand Down Expand Up @@ -85,10 +85,10 @@ void setup() {
Serial.println(TrueRandom.randomByte(),DEC);

// Zero an array
for(i=0; i<arrayLength; i++) array[i]=0;
for(int i=0; i<arrayLength; i++) array[i]=0;

Serial.print("An empty array of bytes: ")
for(i=0; i<arrayLength; i++) {
Serial.print("An empty array of bytes: ");
for(int i=0; i<arrayLength; i++) {
Serial.print(array[i],DEC);
}
Serial.println();
Expand All @@ -98,8 +98,8 @@ void setup() {
// random bytes.
TrueRandom.memfill(array,arrayLength);

Serial.print("A randomised array of bytes: ")
for(i=0; i<arrayLength; i++) {
Serial.print("A randomised array of bytes: ");
for(int i=0; i<arrayLength; i++) {
Serial.print(array[i],DEC);
}
Serial.println();
Expand All @@ -122,4 +122,4 @@ void setup() {

void loop() {

}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=TrueRandom
version=1.2
author=
maintainer=
sentence=Hardware bases random numbers.
paragraph=Generates random numbers using analog pin(avr) or hardware random number generator(nRF5). Compatible to https://github.com/sirleech/TrueRandom
category=Other
url=
architectures=avr,nRF5
Loading