Random numbers are useful for simulations, to create a sense of arbitrariness in games that might make them more “interesting”, i.e. generally speaking: to introduce a level of unpredicatability in the oh-so-deterministic world of today’s computers.

There is an alternative, if you take randomness with a grain of salt:
pseudorandomness. This is a
technique which generates numbers that *appear* random and totally
unrelated, but are in fact produced by carefully designed algorithmic
computations.

It’s easy to generate pseudorandom sequences in software. For simple 8-bit
sequences, something like this will generate a pretty erratic series (unless
`xPrev`

is zero!):

```
uint8_t xNext = xPrev * 211;
```

Variations on that theme will produce longer sequences of larger values. Entire
books have been written about this topic, a web search will turn up many
effective algorithms. But let’s be clear about it: this approach leads to
*anything BUT* unpredictable sequences. If you know the previous state and the
algorithm, you can fully predict all future values.

## Randomness via an ADC

A much higher level of randomness can be obtained by observing some aspect of
the real physical world, and capturing a *noisy signal* (“noise” == “random” in
physics … sort of).

With an ADC, this is easy to do: leave one ADC input pin floating, and measure its analog voltage. The least-significant bit will be the noisiest, always fluctuating due to electrical noise, e.g. the omni-present thermal brownian motion. If we repeat this 32 times and keep only the lower bit, we should get nicely random results:

```
ADC<0> adc;
PinA<0> floatingPin;
uint32_t randomNumber () {
uint32_t r = 0;
for (int i = 0; i < 32; ++i)
r = (r << 1) | (adc.read(floatingPin) & 1);
return r;
}
```

## Randomness hardware

In many STM32 µC’s, there’s also a Random Number Generator (RNG) *hardware*
device. This uses multiple ring
oscillators, combined via XOR
to maximise the noise content.

A ring oscillator can be built with an odd number of logical inverter gates:

In actual use, there will be a lot more than three, but the mechanism is the
same: inverters produce the *opposite* logic level on their output, after a
very slight delay. If you tie an odd number of stages into a ring, you get a
configuration which has no stable state: if the input is “0”, the output will
be “1”, but that output is tied back to the input, so it turns to “1” as well,
flipping the output to “0”. And the cycle repeats - *ad nauseam*, and *ad
infinitum*.

The key is the logic gate delay, especially with a large numbers of inverters.
This delay is temperature and thermal-noise dependent, and changes all the
time. The resulting signal is very high frequency **and** very irregular
**and** (hopefully) independent of the µC’s system clock. So whenever you look
at its output pin, you’ll get to see either “0” or “1”, and it’ll be nearly
unpredicatble (unless you cool it way down to absolute zero) - i.e. nicely
random.

It’s very easy to try this out on an STM32F407, for example:

```
#include <jee.h>
UartDev< PinA<9>, PinA<10> > console;
int printf(const char* fmt, ...) {
va_list ap; va_start(ap, fmt); veprintf(console.putc, fmt, ap); va_end(ap);
return 0;
}
int main() {
console.init();
Periph::bit(Periph::rcc+0x34, 6) = 1; // RNGEN, p.244
constexpr uint32_t rng = 0x50060800;
MMIO32(rng+0x0) = (1<<2); // start the RNG
while (true) {
while ((MMIO32(rng+0x4) & (1<<0)) == 0) {}
printf("%08x\n", MMIO32(rng+0x8));
}
}
```

Here’s some output, this will go on forever, evidently:

```
2E54C269
2395B09C
9B1AB45C
3993E287
32FCF0E7
```