-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathmaplerng.pde
104 lines (91 loc) · 3.19 KB
/
maplerng.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// rng.pde
// use LSI clock and SYSTICK
// use RTC lib, could remove that layer
// based on arduino/teensy Entropy lib
// https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library
#include <stdio.h>
#include <stdint.h>
#include <RTClock.h>
const uint8_t gWDT_buffer_SIZE=32;
const uint8_t WDT_POOL_SIZE=8;
uint8_t gWDT_buffer[gWDT_buffer_SIZE];
uint8_t gWDT_buffer_position;
uint8_t gWDT_loop_counter;
volatile uint8_t gWDT_pool_start;
volatile uint8_t gWDT_pool_end;
volatile uint8_t gWDT_pool_count;
volatile uint32_t gWDT_entropy_pool[WDT_POOL_SIZE];
RTClock rt (RTCSEL_LSI, 200); // RC at 40khz, bout 5ms per bit
uint32_t random() {
uint32_t retVal;
uint8_t waiting;
while (gWDT_pool_count < 1) waiting += 1;
noInterrupts(); // crtical section
retVal = gWDT_entropy_pool[gWDT_pool_start];
gWDT_pool_start = (gWDT_pool_start + 1) % WDT_POOL_SIZE;
--gWDT_pool_count;
interrupts();
return(retVal);
}
static void tick() {
gWDT_buffer[gWDT_buffer_position] = SYSTICK_BASE->CNT;
gWDT_buffer_position++; // every time the WDT interrupt is triggered
if (gWDT_buffer_position >= gWDT_buffer_SIZE)
{
gWDT_pool_end = (gWDT_pool_start + gWDT_pool_count) % WDT_POOL_SIZE;
// The following code is an implementation of Jenkin's one at a time hash
// This hash function has had preliminary testing to verify that it
// produces reasonably uniform random results when using WDT jitter
// on a variety of Arduino platforms
for(gWDT_loop_counter = 0; gWDT_loop_counter < gWDT_buffer_SIZE; ++gWDT_loop_counter)
{
gWDT_entropy_pool[gWDT_pool_end] += gWDT_buffer[gWDT_loop_counter];
gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 10);
gWDT_entropy_pool[gWDT_pool_end] ^= (gWDT_entropy_pool[gWDT_pool_end] >> 6);
}
gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 3);
gWDT_entropy_pool[gWDT_pool_end] ^= (gWDT_entropy_pool[gWDT_pool_end] >> 11);
gWDT_entropy_pool[gWDT_pool_end] += (gWDT_entropy_pool[gWDT_pool_end] << 15);
gWDT_entropy_pool[gWDT_pool_end] = gWDT_entropy_pool[gWDT_pool_end];
gWDT_buffer_position = 0; // Start collecting the next 32 bytes of Timer 1 counts
if (gWDT_pool_count == WDT_POOL_SIZE) // The entropy pool is full
gWDT_pool_start = (gWDT_pool_start + 1) % WDT_POOL_SIZE;
else // Add another unsigned long (32 bits) to the entropy pool
++gWDT_pool_count;
}
}
void setup() {
rt.attachSecondsInterrupt(tick);
gWDT_buffer_position=0;
gWDT_pool_start = 0;
gWDT_pool_end = 0;
gWDT_pool_count = 0;
}
#define REPS 50
void display() {
uint32_t r,t;
int i;
float bps;
t=micros();
for (i=0;i<REPS;i++)r=random();
t= micros() -t;
bps = REPS*32.e6/t;
SerialUSB.println(bps,2);
r=random();
SerialUSB.println(r,HEX);
}
void logger() {
// await start byte from host then start sending random numbers
// ./logger 5000000 for diehard tests
unsigned int rng;
while(!SerialUSB.available()){} // wait for byte
SerialUSB.read();
while(1) {
rng = random();
SerialUSB.write((uint8_t *)&rng,4);
}
}
void loop() {
display();
// logger();
}