Make your own free website on Tripod.com

headerdef.jpg

H O M E - APOLLO181 INTRODUCTION
First Program Example
Binary Clock Algorithm
Shift-and-Add Multiplication
Prime Numbers Benchmark
PWM LED Dimmer
Step Motor Controller
Sound Generator: Part 1
Sound Generator: Part 2
Random Number Generator
EPROM Data Storage
My Previous Z80 Project

 

How to generate a PWM signal for accurate LED brightness control

 

pwm.jpg
APOLLO181 LED brightness at two different PWM duty cycles

This is a simple program to implement a LED dimmer: a PWM signal is used to light the leds at varying brightness according to a 4-bit linear scale made of sixteen steps.

 

PWM, or Pulse Width Modulation, is a great method of controlling analog circuits by using the digital output of a microprocessor.

The PWM signal consists of a modulated square wave. The modulation can change the clock cycle of the signal (frequency) or the percentage of the power delivered during each clock cycle (duty cycle). The amplitude of the signal remains stable during the time.

If we drive a LED with a PWM digital signal, we can effectively control the light output (brightness) by varying the duty cycle: for example if we use a 33% of duty cycle over a short duration of time, we will turn the LED ON for the 33% of the cycle and OFF for the remaining 67% of that time period, so the LED will appear less bright because it does receive a third of the power.

Since humans perceive brightness not in a linear way but logarithmically like hearing response, we need to implement a PWM signal in which the duty cycle varies according to a logarithmic curve.

 

Because implementing transcendental functions via algorithm is cumbersome and the values we need to cover are only sixteen, the most efficient way is to create a sort of look-up table for all the sixteen possible duty cycle values. A duty cycle with 8-bit resolution, with a range from 0 to 255, looks enough for our purpose.

Magnitude Input Magnitude PWM 8-bit 8-bit 8-bit
Scale Switches Scale % Dec Binary  Hex
(Linear) Bin Code (Logarithmic) DC Value DC Value DC Value DC Value
1 0000 1,00 100% 255 1111 1111 FF
2 0001 0,75 75% 191 1011 1111 BF
3 0010 0,60 60% 153 1001 1001 99
4 0011 0,50 50% 127 0111 1111 7F
5 0100 0,42 42% 106 0110 1010 6A
6 0101 0,35 35% 90 0101 1010 5A
7 0110 0,30 30% 76 0100 1100 4C
8 0111 0,25 25% 63 0011 1111 3F
9 1000 0,21 21% 52 0011 0100 34
10 1001 0,17 17% 43 0010 1011 2B
11 1010 0,14 14% 34 0010 0010 22
12 1011 0,10 10% 26 0001 1010 1A
13 1100 0,07 7% 19 0001 0011 13
14 1101 0,05 5% 12 0000 1100 0C
15 1110 0,02 2% 5 0000 0101 05
16 1111 0,00 0% 0 0000 0000 00

To much simplify the algorithm I preferred to program the eight switches of APOLLO181 using the Johnson Counter sequence (i.e. 0000; 0001; 0011; 0111; 1111; 1110; 1100; 1000 ...), in which only one switch changes status for each brightness magnitude step. This is a convenient way to fast switch between 16 distinct states for controlling the duty cycle of the PWM signal.

 

Magnitude Johnson  Magnitude PWM 8-bit 8-bit 8-bit
Scale Counter Scale % Dec Binary  Hex
(Linear) Bin Code (Logarithmic) DC Value DC Value DC Value DC Value
1 00000000 1,00 100% 255 1111 1111 FF
2 00000001 0,75 75% 191 1011 1111 BF
3 00000011 0,60 60% 153 1001 1001 99
4 00000111 0,50 50% 127 0111 1111 7F
5 00001111 0,42 42% 106 0110 1010 6A
6 00011111 0,35 35% 90 0101 1010 5A
7 00111111 0,30 30% 76 0100 1100 4C
8 01111111 0,25 25% 63 0011 1111 3F
9 11111111 0,21 21% 52 0011 0100 34
10 11111110 0,17 17% 43 0010 1011 2B
11 11111100 0,14 14% 34 0010 0010 22
12 11111000 0,10 10% 26 0001 1010 1A
13 11110000 0,07 7% 19 0001 0011 13
14 11100000 0,05 5% 12 0000 1100 0C
15 11000000 0,02 2% 5 0000 0101 05
16 10000000 0,00 0% 0 0000 0000 00

The important factor here is the refresh rate: if we use a frequency that is too much low, we will turn the light on and off too slowly and the viewer will see the LED ‘flickering’ and not a stable light.

So we need a clock cycle beyond the limit of the flicker perception of human eye, and anything faster than 100 Hz would be probably OK. Thus we will adopt in this program an approximate cycle of 180 Hz, that has a period time of 5555 microseconds.

 

Being  3 MHz the clock of APOLLO181 and because every instruction takes four clock cycles, each instruction takes 1/3 * 4 = 1,333333 Ás to be executed.

We will need then to create a precise routine of delay which shall last in total 5555 Ás, that approximately equals to 5555/1,333333 = 4166, about 4096 instructions that consist of 256 cycles of 16 instructions each.

Here APOLLO181 program:

00 E7 ACC = IN PORT [7]
01 B0 Compare ACC with REG0
02 1A ACC = A#
03 C0 IF ZERO GOTO 0A#
04 E7 ACC = IN PORT [7]
05 20 REG [0] = ACC
06 E8 ACC = IN PORT [8]
07 2A REG [A] = ACC
08 10 ACC = 0#
09 01 GOTO 10#
0A E8 ACC = IN PORT [8]
0B BA Compare ACC with REGA
0C 15 ACC = 5#
0D CB IF ZERO GOTO B5#
0E 16 ACC = 6#
0F 00 GOTO 06#
10 3A ACC = REG [A]
11 A8 Compare ACC with 8#
12 10 ACC = 0#
13 C5 IF ZERO GOTO 50#
14 3A ACC = REG [A]
15 AC Compare ACC with C#
16 16 ACC = 6#
17 C5 IF ZERO GOTO 56#
18 3A ACC = REG [A]
19 AE Compare ACC with E#
1A 1C ACC = C#
1B C5 IF ZERO GOTO 5C#
1C 3A ACC = REG [A]
1D AF Compare ACC with F#
1E 11 ACC = 1#
1F CE IF ZERO GOTO E1#
20 30 ACC = REG [0]
21 A8 Compare ACC with 8#
22 18 ACC = 8#
23 C6 IF ZERO GOTO 68#
24 30 ACC = REG [0]
25 AC Compare ACC with C#
26 1E ACC = E#
27 C6 IF ZERO GOTO 6E#
28 30 ACC = REG [0]
29 AE Compare ACC with E#
2A 14 ACC = 4#
2B C7 IF ZERO GOTO 74#
2C 30 ACC = REG [0]
2D AF Compare ACC with F#
2E 17 ACC = 7#
2F CE IF ZERO GOTO E7#
30 3A ACC = REG [A]
31 A7 Compare ACC with 7#
32 10 ACC = 0#
33 C8 IF ZERO GOTO 80#
34 3A ACC = REG [A]
35 A3 Compare ACC with 3#
36 16 ACC = 6#
37 C8 IF ZERO GOTO 86#
38 3A ACC = REG [A]
39 A1 Compare ACC with 1#
3A 1C ACC = C#
3B C8 IF ZERO GOTO 8C#
3C 3A ACC = REG [A]
3D A0 Compare ACC with 0#
3E 1D ACC = D#
3F CE IF ZERO GOTO ED#
40 30 ACC = REG [0]
41 A7 Compare ACC with 7#
42 18 ACC = 8#
43 C9 IF ZERO GOTO 98#
44 30 ACC = REG [0]
45 A3 Compare ACC with 3#
46 1E ACC = E#
47 C9 IF ZERO GOTO 9E#
48 30 ACC = REG [0]
49 A1 Compare ACC with 1#
4A 14 ACC = 4#
4B CA IF ZERO GOTO A4#
4C 30 ACC = REG [0]
4D A0 Compare ACC with 0#
4E 1A ACC = A#
4F CA IF ZERO GOTO AA#
50 1F ACC = F#
51 21 REG [1] = ACC
52 1F ACC = F#
53 22 REG [2] = ACC
54 1A ACC = A#
55 05 GOTO 5A#
56 1F ACC = F#
57 21 REG [1] = ACC
58 1B ACC = B#
59 22 REG [2] = ACC
5A 10 ACC = 0#
5B 06 GOTO 60#
5C 19 ACC = 9#
5D 21 REG [1] = ACC
5E 19 ACC = 9#
5F 22 REG [2] = ACC
60 16 ACC = 6#
61 6 GOTO 66#
62 1F ACC = F#
63 21 REG [1] = ACC
64 17 ACC = 7#
65 22 REG [2] = ACC
66 1C ACC = C#
67 06 GOTO 6C#
68 1A ACC = A#
69 21 REG [1] = ACC
6A 16 ACC = 6#
6B 22 REG [2] = ACC
6C 12 ACC = 2#
6D 07 GOTO 72#
6E 1A ACC = A#
6F 21 REG [1] = ACC
70 15 ACC = 5#
71 22 REG [2] = ACC
72 18 ACC = 8#
73 07 GOTO 78#
74 1C ACC = C#
75 21 REG [1] = ACC
76 14 ACC = 4#
77 22 REG [2] = ACC
78 1E ACC = E#
79 07 GOTO 7E#
7A 1F ACC = F#
7B 21 REG [1] = ACC
7C 13 ACC = 3#
7D 22 REG [2] = ACC
7E 14 ACC = 4#
7F 08 GOTO 84#
80 14 ACC = 4#
81 21 REG [1] = ACC
82 13 ACC = 3#
83 22 REG [2] = ACC
84 1A ACC = A#
85 08 GOTO 8A#
86 1B ACC = B#
87 21 REG [1] = ACC
88 12 ACC = 2#
89 22 REG [2] = ACC
8A 10 ACC = 0#
8B 09 GOTO 90#
8C 12 ACC = 2#
8D 21 REG [1] = ACC
8E 12 ACC = 2#
8F 22 REG [2] = ACC
90 16 ACC = 6#
91 09 GOTO 96#
92 1A ACC = A#
93 21 REG [1] = ACC
94 11 ACC = 1#
95 22 REG [2] = ACC
96 1C ACC = C#
97 09 GOTO 9C#
98 13 ACC = 3#
99 21 REG [1] = ACC
9A 11 ACC = 1#
9B 22 REG [2] = ACC
9C 12 ACC = 2#
9D 0A GOTO A2#
9E 1C ACC = C#
9F 21 REG [1] = ACC
A0 10 ACC = 0#
A1 22 REG [2] = ACC
A2 18 ACC = 8#
A3 0A GOTO A8#
A4 15 ACC = 5#
A5 21 REG [1] = ACC
A6 10 ACC = 0#
A7 22 REG [2] = ACC
A8 1E ACC = E#
A9 0A GOTO AE#
AA 10 ACC = 0#
AB 21 REG [1] = ACC
AC 10 ACC = 0#
AD 22 REG [2] = ACC
AE 40 SET ALU to 0#
AF 31 ACC = REG [1]
B0 70 ACC = Logic f (ACC, 0#)
B1 23 REG [3] = ACC
B2 32 ACC = REG [2]
B3 70 ACC = Logic f (ACC, 0#)
B4 24 REG [4] = ACC
B5 90 SET NO CARRY
B6 31 ACC = REG [1]
B7 2E REG [E] = ACC
B8 32 ACC = REG [2]
B9 2F REG [F] = ACC
BA 10 ACC = 0#
BB F7 OUT PORT [7] = ACC
BC F8 OUT PORT [8] = ACC
BD F9 OUT PORT [9] = ACC
BE FA OUT PORT [A] = ACC
BF 3E ACC = REG [E]
C0 49 SET ALU to 9#
C1 51 ACC = Arithm f (ACC, 1#, CARRY)
C2 2E REG [E] = ACC
C3 3F ACC = REG [F]
C4 50 ACC = Arithm f (ACC, 0#, CARRY)
C5 2F REG [F] = ACC
C6 1A ACC = A#
C7 DC IF CARRY GOTO CA#
C8 1A ACC = A#
C9 0B GOTO BA#
CA 90 SET NO CARRY
CB 33 ACC = REG [3]
CC 2E REG [E] = ACC
CD 34 ACC = REG [4]
CE 2F REG [F] = ACC
CF 1F ACC = F#
D0 F7 OUT PORT [7] = ACC
D1 F8 OUT PORT [8] = ACC
D2 F9 OUT PORT [9] = ACC
D3 FA OUT PORT [A] = ACC
D4 3E ACC = REG [E]
D5 49 SET ALU to 9#
D6 51 ACC = Arithm f (ACC, 1#, CARRY)
D7 2E REG [E] = ACC
D8 3F ACC = REG [F]
D9 50 ACC = Arithm f (ACC, 0#, CARRY)
DA 2F REG [F] = ACC
DB 1F ACC = F#
DC DD IF CARRY GOTO DF#
DD 1F ACC = F#
DE 0C GOTO CF#
DF 10 ACC = 0#
E0 00 GOTO 00#
E1 30 ACC = REG [0]
E2 A0 Compare ACC with 0#
E3 12 ACC = 2#
E4 C6 IF ZERO GOTO 62#
E5 10 ACC = 0#
E6 02 GOTO 20#
E7 3A ACC = REG [A]
E8 AF Compare ACC with F#
E9 1A ACC = A#
EA C7 IF ZERO GOTO 7A#
EB 10 ACC = 0#
EC 03 GOTO 30#
ED 30 ACC = REG [0]
EE AF Compare ACC with F#
EF 12 ACC = 2#
F0 C9 IF ZERO GOTO 92#
F1 10 ACC = 0#
F2 04 GOTO 40#

DISCLAIMER & CREDIT: All data here reproduced are for educational and non-commercial purpose, following fair-use guidelines.

This is an INDIPENDENT AND UNOFFICIAL hobby site. Either Dr. Peter R. Rony or the Blacksburg group or Computer History Museum (Mountain View, CA) or other third-party DO NOT HAVE ANY ASSOTIATION with this work.

Author G.G. DOESN'T EARN ANYTHING FROM ADVERTISEMENT. This site is not in the business of making money. This site is visible thanks to the Free Web Hosting Tripod Service, so it is ad-supported: advertisement contents, costs and revenues are full managed by the service itself. Author does not have any involvement in them. The advertising links in the Site pages and in the pop-up windows are not Author's property. They can change and the Author is non-responsible about their contents and working. The Author is not responsible about the linked sites.
The information presented here is just that: INFORMATION. Use it at your own risk and for only non commercial purpose. The information here presented is believed to be technically correct and everything presented on this site is done so in good faith. Anyhow you (the reader) are responsible for anything that you might do as a result of reading this article. You assume complete and total responsibility for your actions! Author is not responsible for any misuse or damage coming from the reading and using this information.

Text and images from original typewritten Bugbooks I and II in 1974 are permission courtesy of Dr. Peter R. Rony, the original author and sole copyright owner of the Bugbooks I, II, IIA, III, V, and VI.

The background image on the header of each page of the site is "Sunset over western South America" photographed on 12 April 2011 by an Expedition 27 crew member on the International Space Station. (Image credit: NASA). On it I have merged titles and a my photo of TIL302 displays.

Texas Instruments data are Texas Instruments Copyright and reported by Courtesy of Texas Instruments.

 

TERM OF USE: With clear exception for texts and images which are not author's property, Gianluca G. freely authorizes you the downloading, printing and reproducing of APOLLO181 data, texts and images ONLY for non-commercial usage and ONLY if you give a clear reference to its source and project namewithout any right to resell or redistribute them or to compile or create derivative works.

Any rights not expressly granted herein are reserved.

 

Copyright (c) 2012 by Gianluca G. Italy