Path: Home => AVR-EN => Applications => Random ATtiny13 => Random from sine wave   Diese Seite in Deutsch:
 AVR applications Random number generation with ATtiny13 Generating randoms from a sine wave and transmitting those in assembler

## 4 To generate randoms, transmitting those in assembler and analyzing those

If a generated row of random numbers is homogeneous and, if ever, repeats only after very long periods, has been demonstrated with calculated randoms in Chapter 1. After failing to construct a random noise generator (see Chapter 3), but realizing that it works in practice, I thought that probably the collection method (the lowest bit of a 10-bit result) already produces enough randomness. To verify this thought, one would have to take a clean sine wave and to analyze what random numbers this produces. This page shows the results of that analysis.

As the homogenity of such random numbers requires thousands of runs (which an ATtiny13 can perform well), but as the analysis requires at least 2*256 bytes to count, how often a number number occurred in the list, and several thosand bytes to identify repetitions, the analysis cannot be made within the ATtiny13 itself. So I constructed a method to transmit the numbers to a PC, using a standard RS232 interface. As the ATtiny13 has no UART on board, I used software to transmit those. This page shows how this can be made.

## 4.1 Schematic

This here is a RS232 transmitter that produces random rows of bytes and transmits those via the serial interface to the PC.

The ATtiny13 reads on its ADC2 input pin analog voltages, converts those to 10-bit numbers, separates zeroes and 0x03FF from the results, shifts the lowest of its 10 bits into an 8-bit register. If that is completely filled, the random number is converted to hexadecimal format and stored in a small SRAM buffer. If the buffer is filled with 16 of those bytes, the program adds a check byte (the sum of that 17 bytes has to be zero) and a carriage return 0x0D and a line fees character 0x0A and transmits this buffer over the RS232 interface.

The RS232 interface works with 9,600 Bits per second (Baud, Bd), per bit 1 / 9,600 = 104.167 µs are necessary. It transmits one start bit, eight data bits (from 0 to 7) and two stop bits (8N2). Serial output from the ATtiny13 is on portpin PB2. As the MAX232 reverses polarity the start bit from PB2 is low, the stop bits are high and idle level is also high. Only the data bits are not reversed.

The signal on PB2 is connected with the input T1IN of the MAX232. This device produces the necessary voltages V+ and V- of +/-8V with the four capacitors and brings the input signal to the serial RS232 levels. The signal goes to a female DB9 plug, that can be connected to the PC's RS232 plug. The pins Data Carrier Detect (DCD), Request to Send (RTS) and Data Set Ready (DSR) are tied to V+ level with the resistors as shown.

I have written a test program by which the communication of the ATtiny13 with the PC can be tested, see below.

## 4.2 Terminal program on the PC

To communicate the PC needs a terminal program. I use RealTerm for that, because it has all it needs for my purposes and much, much more. And it is easy enough to work with.

RealTerm first needs to know the correct serial port and its properties. Select the tab Port with the dropdown field and select the correct port for your connection. Select the baudrate (9k6 by default) and set the number of stop bits to 2. Use the button Change to activate the connection.

In the tab Display you can adjust the type of output to be displayed. If you want to see the hexadecimal format of your incoming characters, use that. Here, the test device has sent small letters. The line feeds here were inserted with the button \n. The scrambled characters on the beginning were programming pulses. If you want to see characters, choose ANSI.

In the tab Capture one can catch text in a file. This is shown later on.

## 4.3 Test program for the hardware

To test if the hardware is correctly working with the PC via the RS232 interface, I have written the test program >random_test_tn13.asm. The program can be modified with a text editor to fit to your needs, then assemble and burn to the ATtiny13.

The program sends characters to the RS232 interface. It works without interrupts and adjusts the signal duration with delay loops. It works in three modes:
1. swCharOnly: If this option is selected (swCharOnly = 1) the serial interface sends the character that is preselected in swChar every ca. two seconds. So characters with less (Blank 0x20, '0' 0x30, 'A' 0x41) or many bit changes (e. g. 'U' 0x55) can be tested.
2. swNextChar: Tests the output of character series such as 'A' to 'Z', 'a' to 'z', '0' bis '9'. The lower bound is defined in swNextFirst, the upper bound in swNextLast. If the upper bound has been reached, it restarts from the lower bound. Every ca. two seconds a character is transmitted.
3. swString: Transmits every ca. two seconds a predefined character string, that is defined in StringTab:. By default this is "The quick brown fox jumps over the lazy dog", followed by a carriage return and a line feed.
With the latter option selected the following should show up:

Who wants to experiment with the program can change e. g. the baudrate loop counters and so the sensitivity of the baudrate properties.

This is what you get if you change the six in line 110 of the test program from
``````
ldi rmp,(nClock-6)/3
```
```
to "5". nClock is by default 125 (=1,200,000 / 9,600), and the loop counter will be 120 / 3 = 40. Now the recognition of T, e, q, i and k as well as of other characters does not work correct any more.

Increasing the "6" does not change the correct reception, but increasing it to "18" makes transmission too fast. With (125 - 18) / 3 = 35 the upper bound of tolerance is reached.

To vary the loop variable from 125-6 = 119 resp. 125-17 = 108 are 11 clock cycles difference. This bandwidth covers 8,8% of the Baudrate or 845 Baud. Such tolerances are well within the error rate of the internal RC clock generator, so one does not need a crystal to transmit RS232 signals.

Please note that the tolerance depends from the PC interface, too. If your interface produces trash, try some other numbers in the lines 98, 110 and 120 of the test program. As the transmission program works more exact with interrupts, the loop problem does not appear therein.

## 4.4 Measuring program for random number generation

The measuring program works with a timer and with interrupts to generate exact bit lengthes of 104.17 µs, no matter what the controller does elsewhere. The software works as follows:
1. It start the AD converter and interrupts if the result is complete,
2. it checks whether the lower and upper bound of the converter is reached,
3. if not: it shifts the lowest of the 10 bits into a register,
4. if eight bits have been shifted, the register is converted to two bexadecimal characters and stored in an SRAM buffer,
5. if the buffer reaches 16 bytes (=32 hexadecimal ASCII characters), a check byte is added (256 - sum of the 16 bytes) as well as a carriage return and a line feed character, then the transmit is started.
During transmit of the buffer, the collection of bits from the noise input is not performed to avoid interferences of the transmit signal with the noise generator and the AD converter.

## 4.5 A sine wave oscillator as random source

It is obvious that a rectangle generator is not an appropriate source for random. But a sine wave oscillator is worth looking at.

This is a not-too-fast sine wave oscillator that produces a clean signal. Because the ADC is sampling the ADC2 input with 1,200,000 / 128 = 9.375 kHz, the frequency of the oscillator should be significantly smaller. This device produces around 600 Hz sine wave.

### 4.5.1 The program for random sampling and serial transmission

With this input signal we feed the ATtiny13 on the test stand and program random_analysis_tn13_v1.asm into its flash. It now produces random numbers and transmits those formatted as hexadecimals to the RS232 interface.

The program works as follows:
1. The ADC is fixed on the ADC2 input. As the oscillator produces up to 5V input voltage, the reference voltage is the operating voltage.
2. The ADC is started with a clock prescaler of 128 and with interrupts enabled. The ADC complete interrupt sets the flag bAdc.
4. If the transmit routine is not running (OCIE0A is clear) the lowest bit in rAdcL is shifted to carry and then rolled left into the register rRandByte.
5. If after left-roll a one is rolled into carry, the eight bits are complete. If that is the case, the byte is converted to hex-ASCII and stored in the buffer. If the option checksum is selected, the byte is also added to the sum register.
6. If the buffer pointer has reached the end of the 16 byte storage space, the checksum is negated and added, together with a carriage return and a line feed. The buffer pointers for transmit are updated and the transmit phase is started by enabling the OCIE0A bit.
Transmitting is performed like shown in the flow diagram. The compare match int starts with saving SREG and with setting the transmit outpin pin bOut to the current state of the T flag in SREG. The current state of PORTB is read, the T flag overwrites PORTB2 and the result is written to PORTB. This ensures that the change of the output pin appears always first and is independent from any other instructions and their duration.

Then preparation of the next T flag starts. As start, data and stop bits differ, the respective subroutines are listed as relative jumps and register pair ZH:ZL is used to IJMP to the next subroutine. Each subroutine increases Z, subroutine TxStop2 restarts Z from the beginning of the table in JTab:. This algorithm was chosen because it is faster than several comparisions and conditional branches. Because Z is not needed for something else, this is the optimal procedure.

The first step TxStart: checks if the last sent byte was a line feed char. When starting the transmit, a dummy character other than 0x0A must be placed there. If the last transmitted byte would be 0x0A the transmit is stopped by clearing the OCIE0A bit: TC0 counts, but there is no interrupt any more. As a stop bit was transmitted last, the RS232 line remains in idle state.

If the last sent character was not 0x0A, the next byte from the buffer is read to the register rTxByte. After restoring SREG the T flag is set to transmit the start bit. Please note that SREG restoration comes in that case first, otherwise the T flag would be overwritten.

By increasing the address in Z the first data bit is send, by copying the bit 0 to the SREG restauration byte in rSreg. This ensures that the T flag is written when SREG is finally restored. Before that the transmit byte is right shifted for the next bit.

If all bits have been sent (the number of bits depends from the entries in the list), the first stop bit just sets the T flag.

With the second stop bit the Z pointer is set to the beginning of the jump list and the T flag is set.

The execution times in clock cycles of the ATtiny13 are associated to all instructions. At maximum 29 clock cycles are needed, at minimum 23. The difference of six cycles correspond with 5 µs, compared with the duration of a complete bit in 104 µ a relevant time difference. Therefore it is appropriate to start the ISR with the PB2 bit setting and not to wait until all subroutines have been completed. As one can increase the baudrate with that method to up to 38.4 kBd without increasing the ATtiny's clock frequency, it is an appropriate method.

The transmit routine has worked from the beginning, even after several hours of transmission did not even lead to a single failure.

### 4.5.2 Results of sampling

To read the generated data stream with the PC, we start RealTerm, select the port, the baudrate and the stop bits and we immediately see the data mess coming in. What we see is just random numbers, no regularity in this.

To store the data stram, we select the tab window Capture in RealTerm, input a file name (with .txt as extension) and start with the button Start Overwrite. From now on we see the growing file and, in the footline of Realterm, the growing number of bytes that are stored in the file. I stopped the capture when it reached 996 kB, you can see its content in 600_Hz_capture.txt (996 kB), where roughly 450,000 randoms are collected over several hours.

### 4.5.3 Analysis of the random rows

To get more details on that random row I have written a Lazarus program to read and analyze such rows. The Lazarus source code, including the captured file, is available for download here.

After starting we select the file where the captured data is in by clicking into the file field. This immediately leads to the following actions:
1. First the file is read and the number of lines is counted (field Lines).
2. The length of all lines is checked (34 with checksum, 32 without). Only the first and the last line did not pass this check.
3. Then it is checked whether all characters are hexadecimals. All complete lines passed this test.
4. If the checksum is activated, the sum of each line is calculated and ckecked for zero. All complete lines passed this test.
5. All 453,712 randoms were then copied to a byte array and it was counted how often each byte occurred. These occurrences were written to a tab separated file, that has the same name but its extension is .csv. As example this file here. The file can be read with any text editor or imported with LibreOffice and selecting tab characters as separators.
Already this simple test revealed that the randoms generated here are not very homogeneous, but shows similar patterns. In parts single bytes are far from the average (here: 1,772), e. g. 255. The calculated randoms in Chapter 1 are much nicer.

Nicer is the identification of similar rows of numbers, here four numbers in a row. This can be analyzed by pressing the button Find quads. Only seven such quads were found in this collection.

### 4.5.4 Conclusion sine wave oscillator as random generator?

Yes, you can do that, but is not ideal. Astoundingly that the stable and regular sine wave produces randoms at all. Even if those are not distributed ideally.

The ideal solution is to combine both methods: once in a while asking the random generator for some random, and the calculating rows from what the random generator delivered as randoms. the mode swMixed in the software for displaying randoms in Chapter 2 works with this method.

Page top Main page Calculation Display Noise generation

Praise, error reports, scolding and spam please via the comment page to me.