Download this file
// Based on TrueRandom by Peter Knight, Tinker.it!, 2010
#include "Random.h"
#define ANALOG_PIN 1
int randomBitRaw(void) {
uint8_t copyAdmux, copyAdcsra, copyAdcsrb, copyPortc, copyDdrc;
uint8_t bit;
volatile uint8_t dummy;
// Store all the registers we'll be playing with
copyAdmux = ADMUX;
copyAdcsra = ADCSRA;
copyAdcsrb = ADCSRB;
copyPortc = PORTC;
copyDdrc = DDRC;
// Perform a conversion on Analog0, using the Vcc reference
ADMUX = _BV(REFS0) | ANALOG_PIN; // Voltage Reference: AREF, Internal Vref turned off
// Bits 3:0 select the input channel, default here is channel 0 (analog0)
#if F_CPU > 16000000
// ADC is enabled, divide by 32 prescaler
ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS0); // Enable ADC, Prescaler division factor 32
#elif F_CPU > 8000000
// ADC is enabled, divide by 16 prescaler
ADCSRA = _BV(ADEN) | _BV(ADPS2); // Enable ADC, Prescaler division factor 16 => 1MHz ADC clock
#else
// ADC is enabled, divide by 8 prescaler
ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0); // Enable ADC, Prescaler division factor 8
#endif
// Autotriggering disabled
ADCSRB = 0;
// Pull Analog0 to ground
PORTC &= ~_BV(ANALOG_PIN); // set pin LOW
DDRC |= _BV(ANALOG_PIN); // set pin as output
// Release Analog0, apply internal pullup
DDRC &= ~_BV(ANALOG_PIN); // set pin as input
PORTC |= _BV(ANALOG_PIN); // set pin as HIGH => enable internal pullup
// Immediately start a sample conversion
ADCSRA |= _BV(ADSC); // set bit => Start conversion in single conversion mode
// Wait for conversion to complete
while (ADCSRA & _BV(ADSC)) // while bit is set (conversion in progress)...
PORTC ^= _BV(ANALOG_PIN); // toggle internal pullup on pin analog0
// Keep least significant bits
bit = ADCL;
// We're ignoring the high bits, but we have to read them before the next conversion
dummy = ADCH;
// Restore register states
ADMUX = copyAdmux;
ADCSRA = copyAdcsra;
ADCSRB = copyAdcsrb;
PORTC = copyPortc;
DDRC = copyDdrc;
return bit & 1;
}
int randomBitRaw2(void) {
// Software whiten bits using Von Neumann algorithm
//
// von Neumann, John (1951). "Various techniques used in connection
// with random digits". National Bureau of Standards Applied Math Series
// 12:36.
//
for(;;) {
int a = randomBitRaw() | (randomBitRaw()<<1);
if (a==1) return 0; // 1 to 0 transition: log a zero bit
if (a==2) return 1; // 0 to 1 transition: log a one bit
// For other cases, try again.
}
}
int randomBit(void) {
// Software whiten bits using Von Neumann algorithm
//
// von Neumann, John (1951). "Various techniques used in connection
// with random digits". National Bureau of Standards Applied Math Series
// 12:36.
//
for(;;) {
int a = randomBitRaw2() | (randomBitRaw2()<<1);
if (a==1) return 0; // 1 to 0 transition: log a zero bit
if (a==2) return 1; // 0 to 1 transition: log a one bit
// For other cases, try again.
}
}
uint8_t randomByte() {
uint8_t result = 0;
uint8_t i;
for(i=8; i--;) result += result + randomBit();
return result;
}