Download the file
  1. // Based on TrueRandom by Peter Knight, Tinker.it!, 2010
  2.  
  3. #include "Random.h"
  4.  
  5. #define ANALOG_PIN 1
  6.  
  7. int randomBitRaw(void) {
  8. uint8_t copyAdmux, copyAdcsra, copyAdcsrb, copyPortc, copyDdrc;
  9. uint8_t bit;
  10. volatile uint8_t dummy;
  11.  
  12. // Store all the registers we'll be playing with
  13. copyAdmux = ADMUX;
  14. copyAdcsra = ADCSRA;
  15. copyAdcsrb = ADCSRB;
  16. copyPortc = PORTC;
  17. copyDdrc = DDRC;
  18.  
  19. // Perform a conversion on Analog0, using the Vcc reference
  20. ADMUX = _BV(REFS0) | ANALOG_PIN; // Voltage Reference: AREF, Internal Vref turned off
  21. // Bits 3:0 select the input channel, default here is channel 0 (analog0)
  22.  
  23. #if F_CPU > 16000000
  24. // ADC is enabled, divide by 32 prescaler
  25. ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS0); // Enable ADC, Prescaler division factor 32
  26. #elif F_CPU > 8000000
  27. // ADC is enabled, divide by 16 prescaler
  28. ADCSRA = _BV(ADEN) | _BV(ADPS2); // Enable ADC, Prescaler division factor 16 => 1MHz ADC clock
  29. #else
  30. // ADC is enabled, divide by 8 prescaler
  31. ADCSRA = _BV(ADEN) | _BV(ADPS1) | _BV(ADPS0); // Enable ADC, Prescaler division factor 8
  32. #endif
  33.  
  34. // Autotriggering disabled
  35. ADCSRB = 0;
  36.  
  37. // Pull Analog0 to ground
  38. PORTC &= ~_BV(ANALOG_PIN); // set pin LOW
  39. DDRC |= _BV(ANALOG_PIN); // set pin as output
  40. // Release Analog0, apply internal pullup
  41. DDRC &= ~_BV(ANALOG_PIN); // set pin as input
  42. PORTC |= _BV(ANALOG_PIN); // set pin as HIGH => enable internal pullup
  43. // Immediately start a sample conversion
  44. ADCSRA |= _BV(ADSC); // set bit => Start conversion in single conversion mode
  45. // Wait for conversion to complete
  46. while (ADCSRA & _BV(ADSC)) // while bit is set (conversion in progress)...
  47. PORTC ^= _BV(ANALOG_PIN); // toggle internal pullup on pin analog0
  48. // Keep least significant bits
  49. bit = ADCL;
  50. // We're ignoring the high bits, but we have to read them before the next conversion
  51. dummy = ADCH;
  52.  
  53. // Restore register states
  54. ADMUX = copyAdmux;
  55. ADCSRA = copyAdcsra;
  56. ADCSRB = copyAdcsrb;
  57. PORTC = copyPortc;
  58. DDRC = copyDdrc;
  59.  
  60. return bit & 1;
  61. }
  62.  
  63.  
  64. int randomBitRaw2(void) {
  65. // Software whiten bits using Von Neumann algorithm
  66. //
  67. // von Neumann, John (1951). "Various techniques used in connection
  68. // with random digits". National Bureau of Standards Applied Math Series
  69. // 12:36.
  70. //
  71. for(;;) {
  72. int a = randomBitRaw() | (randomBitRaw()<<1);
  73. if (a==1) return 0; // 1 to 0 transition: log a zero bit
  74. if (a==2) return 1; // 0 to 1 transition: log a one bit
  75. // For other cases, try again.
  76. }
  77. }
  78.  
  79. int randomBit(void) {
  80. // Software whiten bits using Von Neumann algorithm
  81. //
  82. // von Neumann, John (1951). "Various techniques used in connection
  83. // with random digits". National Bureau of Standards Applied Math Series
  84. // 12:36.
  85. //
  86. for(;;) {
  87. int a = randomBitRaw2() | (randomBitRaw2()<<1);
  88. if (a==1) return 0; // 1 to 0 transition: log a zero bit
  89. if (a==2) return 1; // 0 to 1 transition: log a one bit
  90. // For other cases, try again.
  91. }
  92. }
  93.  
  94. uint8_t randomByte() {
  95. uint8_t result = 0;
  96. uint8_t i;
  97. for(i=8; i--;) result += result + randomBit();
  98. return result;
  99. }
  100.