Random ATtiny13 => Display
Diese Seite in Deutsch:
Of course, simulation is lengthy and boring, so we need some hardware to make
randoms visible. Here, we display random numbers between 0 and 255*255*255 =
16.711.680 as different colors on a RGB-LED. Switching the three LEDs of
that LED is done with PWM generators, that are constructed in software in an
Random number generation with ATtiny13
Displaying random numbers on a RGB LED in assembler
The three LEDs of the RGB LED are attached to the three port pins PB0 (red LED),
PB1 (green LED) and PB2 (blue LED). The current through the LEDs is controlled
by resistors, which are accomodated to the different forward voltages of the
LEDs. They are designed for a current of 20 mA per LED.
As different LED types have different forward voltages I corrected the three
resistors later on to 100 Ω, 47 Ω and 56 Ω.
That comes nearer to 20 mA than the displayed values. You'll have to
check whether your RGB LEDs are more of type 1 or more of type 2. Set your
operating voltage to 4.6 V or use three AA- or AAA-batteries, the
resistors and measure the currents to find that out.
For those who do not have RGB LEDs of the common-anode type, you can use
common-cathodes as well. Just attach the common cathodes to ground and set
the PORT register bits of PB0, PB1 and PB2 to one in the init routine of the
To adjust the speed of the random number display, a variable resistor with
10 kΩ is attached. The resistor of 33 kΩ reduces the
input voltage of the variable resistor to a range between 0 and 1.1 V.
The internal reference voltage of the ADC is set to this, if you do not change
the default software properties.
To the ADC2 input pin, a noise generator can be attached. This should deliver up
to 1.1 Vpp. If unused, tie ADC2 to ground (which prevents random number
generation from this input pin).
The device has an additional male ISP6 plug, via this the ATtiny13 can be
programmed within the system, and which can also serve as supply.
Die Schaltung hat noch einen ISP6-Stecker, mit dem der ATtiny13 programmiert
werden kann und aus dem auch die 5V-Versorgung bezogen werden kann.
That is how the device with the RGB LED, the ATtiny13 and the noise generator
(see Chapter 3: noise generator) look
like on a breadboard.
Two short videos, with
fast speed here
and with slow speed here
show the action. If your browser does not display the vides, download those to
your computer and open them with your operating-system's favoured video display.
2.2 Program of the ATtiny13
This here shows how the program works. Those who just want to download the source
code, find the assembler source here. The code
can be displayed in HTML format here.
2.2.1 Options to be selected from
To cover different application cases, the program can be configured widely. To
configure it, a few options on top of the source code have to be altered. Use
a simple text editor for that. With the three switches swCalcOnly,
swNoiseOnly and swMixed the sources of the random numbers can be
modified. Only one of those three cases should be enabled. swMixed
generates 15 random numbers by calculation and then sets the seed from the
external noise signal.
In the section Adjustable Const further below in the source code some
hardware properties can be altered. cLedLong selects the maximum duration
over which the number is displayed on the LED (in tens of milliseconds).
PwmFreq selects the frequency of the PWM generator for the LED display.
The lower bound is 19 Hz, the upper 146 Hz.
2.2.2 Pulse width control of color combinations
To generate the pulse-width signals for the three colors, the timer/counter TC0
works in CTC mode: after 64 clock cycles of the ATtiny13 (at a default clock
rate of 1.2 MHz) TC0 clears/restarts and interrupts program execution. This
is the case every 64 / 1.2 = 53.3 µs. Each of those interrupts checks
of the red, green and blue value (in registers rRed, rGreen and rBlue) is
reached. If that is the case, the respective color bit in the register rWork
is cleared. The value in those registers determines the pulse width of these
colors: the higher its value the longer remains the color LED on. After
256 steps = 256 * 53.3 µs = 13,65 ms the PWM cycle is restarted.
The PWM frequency therefore is 73.24 Hz.
To ensure that this switching appears immediately after the interrupt and is
independant from the further instructions to be performed, the output step is
done first of all. That is why the work register rWork is changed
afterwards, and its changed value comes only into effect later on, at the
beginning of the next interrupt.
So, switching off the LEDs is done by comparing the color color values in the
registers rRed, rGreen and rBlue with the counter
rPwm that counts the PWM stages upwards.
If the counter rPwm does not overflow when it is increased, the normal
comparison is done with the color values. Only if the correct value is reached
the respective color bit in rWork is cleared.
If rPwm overflows to zero, a new PWM cycle is started. The number of cycles
in the 16-bit-counter in rCntH:rCntL = R25:R24 is decreased. Its original
content says how often the PWM cycle repeats. It stems from the multiplication
of the variable resistors ADC value, so determines the speed of the display. A
counter value of 73 stands for one second, up to 65535 / 73 = 898 seconds =
14.9 minutes can be achieved.
If this counter does not reach zero, the rWork register is restarted with
the register content of rStart. rStart has all three color bits set, but
not the ones for which the random color is zero. These LEDs are not switched on
from the early start (just because they would never reach rPwm's value throughout
the whole PWM cycle).
If the 16-bit counter has reached zero, three new random values have to be
generated. If those are in any case calculated (Mode 1) or in any case taken from
the external noise source (Mode 2) the two routes are executed. Both cases end up
in the same section: the generation of rStart. Here, all bits are set
that are not zero.
Following the generation of rStart the work register rWork is
set to the same value adn, after restoring SREG, the service routine ends with
RETI. The content of rWork is later written to the port pins, when the
next CTC interrupt occurs.
None of the different diversions of the ISR should require more than 64 clock
cycles. As can be seen, this is not the case, there is enough time left.
2.2.3 Random numbers
If all PWM cycles have been absolved and rCntH:rCntL reaches zero, either
the calculation algorithm is used to generates the three new randoms or those
are taken from the random noise generator. In both cases the values in
rRed, rGreen and rBlue are redefined. Because the decision
whether the three numbers are calculated (see
Chapter 1 or copied from the random noise
storage is decided during assembly, this decision does not require any clock
2.2.4 AD conversion and processing
The AD converter has to measure two channels:
The converter is once started in the init section. The channel multiplexer is
set to ADC3 and the internal reference voltage of 1.1 V is switched on.
The reference voltage assures that even small signal amplitudes generate noise
input. If you use a strong oscillator , like the one described in
Chapter 4, you'll either can
- the adjustment of the speed resistor, and
- incoming signals on the noise generator input.
Further AD conversion is interrupt-driven. If a measurement is complete, the
flag bAdc is set. The associated ISR therefore is rather short and does
not influence the PWM processing. The flag handling is outside the ISR.
- reduce its amplitude down to 1,1 V, or
- you can switch the reference voltage to 5 V by setting the constant
cNoiseHigh in the section Adjustable Const to one. In that
case you'll also have to unmount the pre-resistor from the variable
resistor. Or leave it where it is and increase the display time by five-fold.
Which of the two channels has been measured can be be detected by reading the
MUX port register.
2.2.5 Speed adjustment
If the voltage of the variable resistor has been measured, the 10-bit result
is used for speed adjustment. The higher the voltage, the shorter has the
counter value to be. Therefore the AD result has to be subtracted from 0x0400.
To achieve a speed adjustment that is independent from the rest of the timing
(clock frequency, CTC-divider/PWM frequency, etc.) the value is multiplied
with a constant that incorporates all that. The constant cMultiplier
says: multiply the value to get the 256-fold of the PWM repeat counter
value. If the difference of 0x0400 - ADC is 0x0400 (ADC is at 0 Volt),
the counter value reflects the selected max time, as set in the constant
The multiplication constant cMultiplier
.equ cLedLong = 100 ; Longest delay in tens of ms
is 18, if one second is selected (1023 * 18 = 18,414) and, at 10 seconds,
is 183 and at 100 seconds is 1,831. This constant includes the factor 256,
so skip the LSB of the multiplication result.
.equ cMultiplier = (((cLedLong*clock/(cCtcCmpA+1))+512)/1024)/100
The multiplication of the inverted AD value (10 bits) with this value
requires several registers. The inverted AD value is written to the
registers R3:R2:R1:R0 (R2 and R3 are cleared). The multiplication constant
is in register pair XH:XL.
The registers ZH:ZL:YH:YL hold the result of the multiplication. The upper
8 bits in ZH have to be zero after the multiplication. If not, the result
is limited to 0xFFFF (largest counter value). The lowest 8 bits in YL
are used fou rounding. To avoid zero as result, a one is added.
The multiplication of 1024 (ADC = 0) with 18 yields 18,432. Divided by 256
yields 72, 72 PWM cycles with 13.65 ms each lasts 0.983 seconds. At
max the time can be set to 65,535 * 0.01365 = 894 seconds =
2.2.6 Random numbers from the noise generator
If the MUX was on the ADC2 position and if the result is neither 0 nor 0x03FF,
the lowest bit of the AD result is shifted from the right to the left in the
three registers rRnd3:rRnd2:rRnd1. Because the AD converter works with
a prescaler of 128, requires 14 clock cycles for conversion and has to measure
two channels, the measuring time per bit is 128 * 14 * 2 / 1.200.000 =
3 ms. All 24 bits of a set require 72 ms. This even allows at high
display speed to collect enough random bits. Even if the collection is
incomplete, the left-shifting provides enough random.
If the option swMixed is selected, an additional check is made if the
counter rRndC is at zero. If that is the case, the seed values in
rN1 and rN2 are overwritten by the latest 16 bits random. The counter
counts down in any case where the PWM-ISR calculates three new random
numbers. The counter cRndC is then re-loaded with the constant
cRndCount. So the calculation rows are not too long (see
Chapter 1 for period lengthes).
In both cases the AD converter is restarted with the other channel.
The sleep share of the program is around 65% with these default settings.
This is caused by the many PWM interrupts. If you choose a higher PWM
frequency the supply current can be up to 2 mA (which can be an
issue if your operating current stems from batteries). As the RGB LED
can consume up to 60 mA, the controller is the smaller contributor.
Praise, error reports, scolding and spam please via the
©2020 by http://www.avr-asm-tutorial.net