Arduino Due uses an Atmel SAM3X8E ARM Cortex-M3 CPU, which has a native hardware based True Random Number Generator (TRNG). In this post, we will take a brief look at how to use it in the Arduino environment and take a look at some of its statistical characteristics.
The code below shows the easiest way to use the built-in TRNG:
void setup() { Serial.begin(9600); pmc_enable_periph_clk(ID_TRNG); trng_enable(TRNG); } void loop() { uint32_t t = trng_read_output_data(TRNG); Serial.println(t); delay(10); }
pmc_enable_periph_clk is defined in hardware/arduino/sam/system/libsam/source/pmc.c, and trng_enable, trng_read_output_data are both defined in hardware/arduino/system/libsam/source/trng.c. Technically speaking we need to wait till the random number generator is ready before reading the output data. But since the TRNG on SAM3X8E is fast (one random number for every 84 clock cycles), we can safely ignore it here. In the code above, each generated random number is treated as an unsigned 32 bit integer.
Alternatively, we can enable TRNG interrupt and use an interrupt handler to retrieve the generated random number when it is ready:
void setup() { Serial.begin(9600); pmc_enable_periph_clk(ID_TRNG); trng_enable(TRNG); NVIC_DisableIRQ(TRNG_IRQn); NVIC_ClearPendingIRQ(TRNG_IRQn); NVIC_SetPriority(TRNG_IRQn, 0); NVIC_EnableIRQ(TRNG_IRQn); trng_enable_interrupt(TRNG); } void TRNG_Handler(void) { uint32_t stat = trng_get_interrupt_status(TRNG); if ((stat & TRNG_ISR_DATRDY) == TRNG_ISR_DATRDY) { int r = trng_read_output_data(TRNG); Serial.println(r); } } void loop() { }
Here we are checking the TRNG ISR status to ensure that the random number has been generated before reading the output data. Note that the result returned trng_read_output_data can be interpreted as either signed or unsigned numbers. In this particular example we are treating it as a signed 32 bit integer and thus the returned random number series will be distributed evenly around 0. Nested vectored interrupt controller NVIC_* routines are inlined in hardware/arduino/sam/system/CMSIS/CMSIS/Include/core_cm3.h.
The datasheet states that the TRNG in SAM3X8E passes the American NIST Special Publication 800-22 and Diehard Random Tests. Here we will take a look at some of the statistical characteristics of the pseudo random numbers generated via SAM3X8E. For the analysis below, I used the code listed above and generated 1 million samples.
The first figure shows the autocorrelation of the random number series when 1000 samples are used. The second figure shows the autocorrelation when 10,000 samples are used. As more samples are used, the autocorrelation of the sequence across different lags slowly converges to zero, indicating that the sequence is independently and identically distributed.
Here is the autocorrelation plot when the entire sample sequence (1 million) is used. As you can see, the autocorrelations are virtually zero across different lags.
Here are two pictures showing the histogram and power spectrum density of the 1,000,000 samples. From these plots, we can infer how even these random numbers are distributed.
Here is another visual representation of the 1,000,000 sample data from the TRNG. The data is arranged into a 1000×1000 matrix and the color indicates the magnitude of the value at that point: