Applications => Magic circle
AVR single chip microcontrollers AT90S, ATtiny, ATmega and ATxmega
Magic circle with ATtiny2313 and LEDs
Magic circle with ATtiny2313
An application of the controller with 13 LEDs with PWM driven intensity,
preferably as a gift or displaying in the window.
Switching LEDs on and off is simple, everybody can program that using the CBI and
SBI instructions in assembler (or in whatever language you prefer).
In that case the switching on works with 256 stages of increasing intensity,
the switching off with the same number of stages with decreasing intensity.
Call that soft on and off. Double speed in that case means reducing the number
of stages down to 128, very fast speed means 64 stages. To not getting bored by
the ever same speed, you can mix those speeds a little bit, so nobody goes to
The intensity regulation is performed with four PWM channels in the ATtiny2313,
where the four PWM output pins OCR0A, OCR0B, OCR1A and OCR1B of the two
timer/counters TC0 and TC1 toggle. Every output pin drives between two and
four LED cathodes. This brings the output pins to their electical limits
and active-low voltages are at 0.88 V (with four LEDs actively driven).
As each anode output pin has to drive only one single LED, their active-high
voltage is by 0.3 V below the operating voltage.
The display sequences are stored in a table in the flash memory, can be adjusted
to your personal taste, so each device gift has an individual design and is
2.1 Controller part
This is the whole boring scheme. Each LED is driven with a resistor
(in this case with an operating voltage of 3.3 V with 33 Ω.
On average a LED current of 7.2 mA (between 5.7 and 9.2 mA) has
been measured. The voltage of the LED at this current is roughly 2.0 V
(with 5 mm standard LEDs).
Attached is a ISP6 interface that allows to program the device within the
system. Unfortunately my ancient AVR-ISP-MkII does not work at 3.3 V
operating voltage. Either it is defective or programming voltage too low.
Another programming device worked fine. If you encounter similar problems,
switch off the 33 Ω with three jumpers during programming.
2.2 Power supply
The power supply was built with a 2 VA transfor4mer with
2 * 7,5 V.
As regulator a LM317 was used, which is adjusted with a 10-speed
potentiometer of 1 kΩ to 3.3 V output voltage.
Of course you can use a 3.3 V regulator instead if you have
If a 5 V power supply shall be used the resistors driving
the LEDs have to be increased to 180 or 220 Ω.
The LM317 generates at maximum 600 mA heat, so either you
can use no or only a small heat sink. At elevated LED currents
a 20°C/W heat sink is sufficient.
These are the voltages with a consumption of 130 mA.
All capacitors are specified with 35 V, because the transformer
produces a very high voltage when no load is attached (compensation
of the inner resistance of 22,7 Ω per coil). Without
a load the 7,5 V coils produces more than 16 V after
rectification. Especially tantal capacitors do not survive that
The software for calculating the power supply voltages can be
3.1 Controller part
Mounting the controller part is on a 40*40 mm breadboard.
The LED cathode and anode connections are on soldering pins
of 1 mm. If you want to have a plug instead use an
18- or 20-pin IDC connector instead.
That is how the board looks like after soldering the LEDs.
3.2 Mounting the power supply
The power supply components fit to a 50*60 mm breadboard.
Especially the 230/110 V side needs some attention: the
mounting screws shall not have contact with the fuse connections.
That is how the power supply looks like. The type plate of the
transformer is the other way around, presumably that is why it
was so cheap.
3.3 Mounting into a box
The whole electronics fits into a small 120-by-60-by-40 mm
plastic box, which is equipped with a small
type plate (in Open-Office-Graphic format),
and four rubber foots and finally delivered with a user manual
in PDF or
in Open-Office-Writer format to the
4.1 Structure of the software
During init all three ports A, B and D that are used
to drive the LEDs are written to ones. The direction
ports of the output pins OC0A, OC0B, OC1A and OC1B
are set, all anode output pins are cleared (all LEDs
off). The pointer Z is set to the beginning of the
sequence table. Both timers are started with a precaler
of 8 and all OC outputs are set to toggle (0 on the
beginning of the PWM cycle, toggle when reaching the
Following init, the software runs interrupt-driven.
For this, the CompareA interrupt of timer/counter TC0
is used, which is triggered after each complete PWM
phase. The interrupt-service-routine then sets the
compare values of all four PWM channels to the value
in the register rPwm. This register is then either
increased (flag bFall = 0) or decreased (flag bFall
= 1). If the flag bFast is one increase and decrease
are by one additional step, if the flag bVeryFast
is one, two additional steps are performed.
If the register rPwm overflows (bFall=0) and if the
flag bUpOnly is set, the rPwm restarts at zero. If
bUpOnly=0 then bFall is set.
If the counter rPwm reaches zero (bUpOnly=0 and
bFall=1) or if it overflows (bUpOnly=1), the flag
bStart will be set. This flag is processed outside the
interrupt service routine: the next three LED anode
combinations are read from the table and are written
to the three direction ports. All LEDs that should be
on in the next period have their direction bit set
and the portpin gets high.
The processing steps are described in the next chapter.
4.2 Processing steps
All processing steps are laid down in a table. This
usually holds four data bytes:
If the flag byte has the following values, the process
is controlled and only one following byte is read:
- First byte: Flags: The flags can be normal (0),
upwards only (bit 0 = 1), double speed (bit 1 = 1)
or fourfold speed (bit 1 and 2 = 1).
- Second byte: The direction bits for port D (with
bit 6 always set).
- Third byte: The direction bits for port B (with
bits 2, 3 and 4 always set).
- Fourth byte: The direction bits for port A.
To ease the construction of the process table, the file
constants.inc defines bit
combinations, that can be used to write data to the table.
For example the values for no LED on and for all LEDs on
- 0xFF: End of the table, restart at the beginning,
- 0xFE: Repeat the following entries in an outer
loop, the number of repetitions is encoded in the
second byte, the starting address is copied to the
- 0xFD: Repeat the following entries in an inner
loop, the number of repetitions is encoded in the
second byte, the starting address of this sequence
is written to registers Y,
- 0xFC: End of the outer repetition loop, if further
repetion is required the address is restored from X,
if after n repetitions, the execution is continued
after the current address.
- 0xFB: End of the inner repetition loop, if further
repetition is required the address is restored from Y,
if not the execution is continued on the next
.equ X0=1843200 ; 00.1C.20.00
.equ Xall=67075840 ; 03.FF.7F.00
the LEDs one and two are switched on.
.set cX = X1
.set cX = X2
This turns both LEDs on.
.set cX = X1_2
The flags bUpOnly, bFast and bVeryFast are simply added
to this constant, e.g. very fast on/off of LED 2:
By using the repetition control up to 256 repetitions
can be encoded without having to copy the sequence
n times. This repeats the sequence LED 1, LED 2 and
LED 3 for four times.
.set cX = cVeryFast+X2
With cRepeat1 and cRepeat2 nested repetitions can be
.db cRepeat1,4 ; Start outer repetion, count = 4
.set cX = X1
.set cX = X2
.set cX = X3
.db cNext1,0 ; Repeat outer loop three times
If necessary the spread sheet Tables.ods
in Open-Office format allows to design and calculate
combinations. The sheet Bit_Tab allows that. Just
Make sure that the changed table always ends with
0xFF,0xFF, so that execution restarts.
- add a name for the constant in column A,
- write a 1 in all locations L1 to L13 for each
LED, that should be on, and
- copy the definition result in column S and
paste it to the file constants.inc,
- add the constant to the process table,
- assemble magic_circle_v1.asm.
The assembler source code is
here in assembler format and
here in HTML format.
For assembling the Include file constants.inc
is additionally required in the same path as the .asm file.
No fuses have to be changed.
Have fun with the soft blinker.
Praise, dispraise, error reports, criticaster, scolding and unqualified spam
please via the
comments page to me.
©2017 by http://www.avr-asm-tutorial.net