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;
}