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

An exhaustive use of the 74181: a binary chronograph

The following algorithm shows a good test of  APOLLO181 processor: the program performs a binary chronograph that displays traditional sexagesimal time in binary format. This algorithm is interesting and exhaustive as:

1) it fills all the available RAM, which is only 256 bytes

2) it employs the entire set of instructions

3) it benefits from the fixed-length feature of the instructions to calculate exact timing

4) it exhaustively uses the 74181 ALU, performing in one shot combined arithmetic and logical operations (such as: "(A OR B) PLUS (A AND NOT(B))" ), which are far enough away from the traditional use of the chip.

If you analyze the algorithm, at first glance it will seem that contains many redundant instructions.

The algorithm consists in 256 instructions but it is structured in such a way that, apart from the initialization of the registers to zero, it performs always an infinite loop of exactly 167 instructions. The length of the cycle is always the same (167 instructions), even when the execution meets different conditional paths, for example, during verification of the end-count of seconds, minutes or hours. The cycle length (167 instructions) is always the same, even when we choose to display the time in "minutes & seconds" or "hours & minutes." This explains why additional fixed-paths and redundant instructions are included in all the different conditional paths.

We will see later why it is so important that the algorithm shall last the same amount of time regardless any possible conditional path.

One hour of time is divided into 60 minutes, and one minute is divided into 60 seconds. So we need to build via software a divide by 60 counter, that means a 0 to 59 counter which clears itself when it reaches number sixty.

Decimal 60 (sixty) equals the binary number "0011 1100", which requires two nibbles to be represented and stored in two 4-bit registers.

If we assotiate in the 74181 ALU the lower order nibble (="1100") to a 4-bit "Word A" and the upper nibble (="0011") to a 4-bit "Word B", the end counting condition (sixty) is univocally satisfied as soon as the ALU result matches the 4-bit binary number "1011 with Carry" after having performed the following arithmetic and logic operation:

(A OR B) PLUS (A AND NOT(B)) =

= ("1100" OR "0011") + ("1100" AND NOT "0011") =

= ("1100" OR "0011") + ("1100" AND  "1100") =

= "1111" + ("1100" AND  "1100") =

= "1111" + "1100" =

= "0001 1011" =

= "1011 with Carry"

You may find the arithmetic function "(A OR B) PLUS (A AND NOT(B))" ranked number six in the Texas Instruments 74181 truth table (active high data), when the select binary inputs S3,S2,S1,S0 are respectively 0,1,0,1.

In APOLLO181 the piece of code is:

 … 45 SET ALU to (A OR B)PLUS(A AND NOT(B)) 90 SET FLAG "NO CARRY" 35 ACC = REG5 66 ACC= (ACC OR REG6)+(ACC AND NOT(REG6)) 24 REG4 = ACC 1y Dx IF CARRY GOTO xy … xy 1B ACC = "1011" (= Bh) B4 COMPARE: REG4 = ACC ? 1z Ct IF ZERO GOTO tz … tz 10 ACC = 0h 25 REG5 = ACC 26 REG6 = ACC …

where registers REG5 and REG6 contain the lower and upper nibbles representing seconds, while register REG4 contains the temporary result.

The registers REG7 and REG8 form the nibbles of the minutes and are controlled by the same algorithm.

 COUNTER: REG3 REG2 REG1 REG0 SECONDS: REG6 REG5 MINUTES: REG8 REG7 HOURS: REGA REG9 TEMP REG 4

One day is divided into 24 hours. So we need to build via software a divide by 24 counter, that means a 0 to 23 counter which clears itself when it reaches number twenty-four. This case is more simple as decimal 24 (twenty-four) equals the binary number "0001 1000", which, also this, requires two nibbles to be represented and stored in two 4-bit registers.

But we may notice that if we shift left both the nibbles, we obtain the simply binary number "0011 0000" (or 48 in decimal).

If we associate in the 74181 ALU both the original nibbles ("1000" "0001") to a 4-bit "Word A", the "twenty-four" end counting condition is univocally satisfied as soon as the ALU result matches the binary number "0011", after having performed twice the "shift left with carry" operation:

A= "1000" (with Carry=0)

Shift Left A with Carry =

= A + A + Carry =

= "1000" + "1000" + 0 =

= "0000" with Carry

A= "0001" (with Carry=1, set by previous operation)

Shift Left A with Carry =

= A + A + Carry =

= "0001" + "0001" + 1 =

= "0010" + Carry =

= "0011"

You may find the arithmetic function "A PLUS A" (i.e. Shift Left) ranked number thirteen in the Texas Instruments 74181 truth table (active high data), when the select binary inputs S3,S2,S1,S0 are respectively 1,1,0,0.

Remember that in the 74181, single operand commands (e.g., A PLUS A) operate only on the accumulator (Word A).

In APOLLO181 the piece of code is

 … 4C SET ALU to A PLUS A (Shift Left) 90 SET FLAG "NO CARRY" 39 ACC = REG9 50 ACC= ACC + ACC + CARRY 3A ACC = REGA 50 ACC= ACC + ACC + CARRY A3 COMPARE: ACC = "0011" ? 1y Cx IF ZERO GOTO xy … xy 10 ACC = 0 29 REG9 = ACC 2A REGA = ACC …

where registers REG9 and REGA contain the lower and upper nibbles representing hours in 24-hour notation.

Now that we are able to count seconds, minute and hours, we need to calculate the number and the length of the cycles which have to last exactly one second.

Being in this case 2,4576 MHz the clock of APOLLO181 and because every instruction takes four clock cycles, every instruction takes 1/2.457.600*4 = 1,62760416666667 µs to be executed. We will need to create a precise routine of delay which shall last in total one second, that equals 1/0,00000162760416666667 = 614.400 instructions.

Since each cycle of the counter is made of about a hundred of instructions (I've found at the end that the cycle will result of 167 instructions), we need  to build via software a 16-bit counter by incrementing sequentially four 4-bit separate registers: REG0, REG1, REG2 and REG3.

Every 614.400 / 167 = 3679 counts will last one second, so seconds shall be incremented every 3679 counts. When the counter will reach "0E5F" in hexadecimal (= 3679 in decimal) it will reset itself and will restart to count again.

So every 3679 cycles of 167 instructions will make one second, every 60 seconds will make one minute, every 60 minutes will make 1 hour and every 24 hours will make 1 day. After that everything restarts again.

The accuracy of APOLLO181 chronograph algorithm depends on both hardware TTL clock precision and software correctness.

Apart the deviation of the crystal drift from its mean value (due to age, temperature, power supply voltage and load impedance), we can measure the algorithm precision as follows:

1 / (1 / 2,4576 MHz * 4 * 167) * 10^6 = 3679,04 cycles per sec

3679 / 3679,04 = 0,99998912759 = 99,9989 % precision

60 sec * 60 min * 24 hours = 86400 sec per day

0,99998912759 * 60 * 60 * 24 = 86399 sec per day

86399 sec - 86400 sec = -1 sec per day

According to the calculation, this leads to a software error component of one second per day.  We know that TTL parallel resonant clock circuits are prone to oscillate at unwanted frequencies, and in fact I have experienced that the hardware error component at 2,5 MHz is much higher.

Here below the 256 byte algorithm of the digital binary chronograph.

00   10   ACC = 0

01   F7   PORT7 = ACC

02   F8   PORT8 = ACC

03   F9   PORT9 = ACC

04   FA   PORTA = ACC

05   20   REG0 = ACC

06   21   REG1 = ACC

07   22   REG2 = ACC

08   23   REG3 = ACC

09   25   REG5 = ACC

0A   26   REG6 = ACC

0B   27   REG7 = ACC

0C   28   REG8 = ACC

0D   29   REG9 = ACC

0E   2A   REGA = ACC

0F   2D   REGD = ACC

1    10   90   SET FLAG "NO CARRY"

2    11   49   SET ALU to "1001"

3    12   30   ACC = REG0

4    13   51   ACC = ACC + 1

5    14   20   REG0 = ACC

6    15   31   ACC = REG1

7    16   50   ACC = ACC + 0 + CARRY

8    17   21   REG1 = ACC

9    18   32   ACC = REG2

10   19   50   ACC = ACC + 0 + CARRY

11   1A   22   REG2 = ACC

12   1B   33   ACC = REG3

13   1C   50   ACC = ACC + 0 + CARRY

14   1D   23   REG3 = ACC

15   1E   10   ACC = 0

16   1F   24   REG4 = ACC

17   20   4E   SET ALU to "1110"

18   21   1F   ACC = F

19   22   B0   COMPARE REG0

20   23   1A   ACC = A

21   24   C2   IF ZERO GOTO 2Ah

22   25   34   ACC = REG4

23   26   70   ACC = ACC OR 0

24   27   24   REG4 = ACC

25   28   1F   ACC = F

26   29   02   GOTO 2Fh

22   2A   34   ACC = REG4

23   2B   71   ACC = ACC OR 1

24   2C   24   REG4 = ACC

25   2D   1F   ACC = F

26   2E   02   GOTO 2Fh

27   2F   15   ACC = 5

28   30   B1   COMPARE REG1

29   31   18   ACC = 8

30   32   C3   IF ZERO GOTO 38h

31   33   34   ACC = REG4

32   34   70   ACC = ACC OR 0

33   35   24   REG4 = ACC

34   36   1D   ACC = D

35   37   03   GOTO 3Dh

31   38   34   ACC = REG4

32   39   72   ACC = ACC OR 2

33   3A   24   REG4 = ACC

34   3B   1D   ACC = D

35   3C   03   GOTO 3Dh

36   3D   1E   ACC = E

37   3E   B2   COMPARE REG2

38   3F   16   ACC = 6

39   40   C4   IF ZERO GOTO 46h

40   41   34   ACC = REG4

41   42   70   ACC = ACC OR 0

42   43   24   REG4 = ACC

43   44   1B   ACC = B

44   45   04   GOTO 4Bh

40   46   34   ACC = REG4

41   47   74   ACC = ACC OR 4

42   48   24   REG4 = ACC

43   49   1B   ACC = B

44   4A   04   GOTO 4Bh

45   4B   10   ACC = 0

46   4C   B3   COMPARE REG3

47   4D   14   ACC = 4

48   4E   C5   IF ZERO GOTO 54h

49   4F   34   ACC = REG4

50   50   70   ACC = ACC OR 0

51   51   24   REG4 = ACC

52   52   19   ACC = 9

53   53   05   GOTO 59h

49   54   34   ACC = REG4

50   55   78   ACC = ACC OR 8

51   56   24   REG4 = ACC

52   57   19   ACC = 9

53   58   05   GOTO 59h

54   59   34   ACC = REG4

55   5A   AF   COMPARE "1111"

56   5B   15   ACC = 5

57   5C   C6   IF ZERO GOTO 65h

58   5D   10   ACC = 0

59   5E   10   ACC = 0

60   5F   10   ACC = 0

61   60   10   ACC = 0

62   61   10   ACC = 0

63   62   90   SET FLAG "NO CARRY"

64   63   1D   ACC = D

65   64   06   GOTO 6Dh

58   65   10   ACC = 0

59   66   20   REG0 = ACC

60   67   21   REG1 = ACC

61   68   22   REG2 = ACC

62   69   23   REG3 = ACC

63   6A   9F   SET FLAG "WITH CARRY"

64   6B   1D   ACC = D

65   6C   06   GOTO 6Dh

66   6D   49   SET ALU to "1001"

67   6E   35   ACC = REG5

68   6F   50   ACC = ACC + 0 + CARRY

69   70   25   REG5 = ACC

70   71   36   ACC = REG6

71   72   50   ACC = ACC + 0 + CARRY

72   73   26   REG6 = ACC

73   74   45   SET ALU to "0101"

74   75   90   SET FLAG "NO CARRY"

75   76   35   ACC = REG5

76   77   66   ACC = (ACC OR REG6) + (ACC AND NOT(REG6))

77   78   24   REG4 = ACC

78   79   1F   ACC = F

79   7A   D7   IF CARRY GOTO 7Fh

80   7B   10   ACC = 0

81   7C   10   ACC = 0

82   7D   13   ACC = 3

83   7E   08   GOTO 83h

80   7F   1B   ACC = B

81   80   B4   COMPARE REG4

82   81   19   ACC = 9

83   82   C8   IF ZERO GOTO 89h

84   83   10   ACC = 0

85   84   10   ACC = 0

86   85   10   ACC = 0

87   86   90   SET FLAG "NO CARRY"

88   87   1F   ACC = F

89   88   08   GOTO 8Fh

84   89   10   ACC = 0

85   8A   25   REG5 = ACC

86   8B   26   REG6 = ACC

87   8C   9F   SET FLAG "WITH CARRY"

88   8D   1F   ACC = F

89   8E   08   GOTO 8Fh

90   8F   49   SET ALU to "1001"

91   90   37   ACC = REG7

92   91   50   ACC = ACC + 0 + CARRY

93   92   27   REG7 = ACC

94   93   38   ACC = REG8

95   94   50   ACC = ACC + 0 + CARRY

96   95   28   REG8 = ACC

97   96   45   SET ALU to "0101"

98   97   90   SET FLAG "NO CARRY"

99   98   37   ACC = REG7

100  99   68   ACC = (ACC OR REG8) + (ACC AND NOT(REG8))

101  9A   24   REG4 = ACC

102  9B   11   ACC = 1

103  9C   DA   IF CARRY GOTO A1h

104  9D   10   ACC = 0

105  9E   10   ACC = 0

106  9F   15   ACC = 5

107  A0   0A   GOTO A5h

104  A1   1B   ACC = B

105  A2   B4   COMPARE REG4

106  A3   1B   ACC = B

107  A4   CA   IF ZERO GOTO ABh

108  A5   10   ACC = 0

109  A6   10   ACC = 0

110  A7   10   ACC = 0

111  A8   90   SET FLAG "NO CARRY"

112  A9   11   ACC = 1

113  AA   0B   GOTO B1h

108  AB   10   ACC = 0

109  AC   27   REG7 = ACC

110  AD   28   REG8 = ACC

111  AE   9F   SET FLAG "WITH CARRY"

112  AF   11   ACC = 1

113  B0   0B   GOTO B1h

114  B1   49   SET ALU to "1001"

115  B2   39   ACC = REG9

116  B3   50   ACC = ACC + 0 + CARRY

117  B4   29   REG9 = ACC

118  B5   3A   ACC = REGA

119  B6   50   ACC = ACC + 0 + CARRY

120  B7   2A   REGA = ACC

121  B8   4C   SET ALU to "1100"

122  B9   90   SET FLAG "NO CARRY"

123  BA   39   ACC = REG9

124  BB   50   ACC = ACC + ACC + CARRY

125  BC   3A   ACC = REGA

126  BD   50   ACC = ACC + ACC + CARRY

127  BE   A3   COMPARE "0011"

128  BF   16   ACC = 6

129  C0   CC   IF ZERO GOTO C6h

130  C1   10   ACC = 0

131  C2   10   ACC = 0

132  C3   10   ACC = 0

133  C4   1B   ACC = B

134  C5   0C   GOTO CBh

130  C6   10   ACC = 0

131  C7   29   REG9 = ACC

132  C8   2A   REGA = ACC

133  C9   1B   ACC = B

134  CA   0C   GOTO CBh

135  CB   10   ACC = 0

136  CC   E9   ACC = PORT9

137  CD   2C   REGC = ACC

138  CE   45   SET ALU to "1010"

139  CF   AF   COMPARE "1111"

140  D0   1C   ACC = C

141  D1   CD   IF ZERO GOTO DCh

142  D2   3C   ACC = REGC

143  D3   BB   COMPARE REGB

144  D4   10   ACC = 0

145  D5   CE   IF ZERO GOTO E0h

146  D6   8D   ACC = NOT (REGD)

147  D7   2D   REGD = ACC

148  D8   3C   ACC = REGC

149  D9   2B   REGB = ACC

150  DA   16   ACC = 6

151  DB   0E   GOTO E6h

142  DC   10   ACC = 0

143  DD   10   ACC = 0

144  DE   10   ACC = 0

145  DF   10   ACC = 0

146  E0   3D   ACC = REGD

147  E1   2D   REGD = ACC

148  E2   3B   ACC = REGB

149  E3   2B   REGB = ACC

150  E4   16   ACC = 6

151  E5   0E   GOTO E6h

152  E6   1F   ACC = F

153  E7   BD   COMPARE REGD

154  E8   1C   ACC = C

155  E9   CE   IF ZERO GOTO ECh

156  EA   16   ACC = 6

157  EB   0F   GOTO F6h

156  EC   37   ACC = REG7

157  ED   F7   PORT7 = ACC

158  EE   38   ACC = REG8

159  EF   F8   PORT8 = ACC

160  F0   39   ACC = REG9

161  F1   F9   PORT9 = ACC

162  F2   3A   ACC = REGA

163  F3   FA   PORTA = ACC

164  F4   1E   ACC = E

165  F5   0F   GOTO FEh

158  F6   35   ACC = REG5

159  F7   F7   PORT7 = ACC

160  F8   36   ACC = REG6

161  F9   F8   PORT8 = ACC

162  FA   37   ACC = REG7

163  FB   F9   PORT9 = ACC

164  FC   38   ACC = REG8

165  FD   FA   PORTA = ACC

166  FE   10   ACC = 0

167  FF   01   GOTO 10h