Ipso Facto
Issue 5, Page 36

The 1802 Music Machine

by Cec Williams

It is well known by most experimenters that music is made up of different frequencies and durations, plus pauses (or rests) of different durations. It is also known that a microprocessor is eminently capable of deriving such frequencies, and outputting them from a serial output port. In the case of the CD1802 microprocessor by RCA, as used in the COSMAC Elf, the Q-output port can be programmed to play a melody, via any suitable amplifier and loudspeaker, or even 10 - 20" of wire!

Several music programs were studied, including those in the November 1977 Interface Age, and in the February 1978 Popular Electronics. While they worked well, within their limitations, it was decided to make a program with some features that would be more flexible. This would enable even a neophyte musician the knowledge to program in his own melodies. Some useful features of the program are:

The Music Byte

Each data byte that is used to program a melody has its 8 data bits broken up into 3 parts, as shown in Figure 1. The 4 low bits define the note frequency, the next 3 bits define the duration, while the high bit defines which octave is chosen. The resultant data byte is called a Music Byte.

Bit 7 = octave bit, bits 6-4 = duration bits, bits 3-0 = note bits.
Figure 1

Note Bits: Whether the note to be coded is in the high or the low octave, the 4 note bits are always coded in HEX-code as the lower HEX-digit, shown in Table 1.

Music Code: A B C D E F G A# /
B-flat
C# /
D-flat
D# /
E-flat
F# /
G-flat
G# /
A-flat
rest
Low Hex Digit: A B C D E F 9 4 5 6 7 8 0
Table 1

In Table 1, a "#" is a sharp, a half-tone above the basic note, and a "flat" is a half tone below the basic note.

Duration Bits: For the duration of a note, music works in a binary fashion. Some basic common notes are quarter notes, eighth notes, sixteenth notes, etc., known as crotchets, quavers and semiquavers, respectively. They sometimes have a dot placed after them, which increases their duration by 50%. Such an increase can easily be coded in a binary system. Some examples are shown in Table 2.

Music Code Duration Duration Bits
sixteenth note 1/16 note 0 0 1
eighth note 1/8 note 0 1 0
three-sixteenths note 3/16 note 0 1 1
quarter note 1/4 note 1 0 0
three-eighths note 3/8 note 1 1 0
eighth rest 1/8 rest 0 1 0
quarter rest 1/4 rest 1 0 0
Table 2

Octave Bit: The program has one basic low octave of twelve semi-tones programmed into it. This octave includes the seven basic notes labelled A to G, plus the five sharps or flats. To derive the high octave of notes, the program doubles the pitch of these low notes. This is triggered by programming a '1' in the octave bit. Same examples show how the music byte is built up, and then converted to HEX-code:

Theory Of Operation

The program shown in Table 4 is walked-through in some detail below. This has been done to help neophyte programmers like myself and others, to be better able to grasp the use of some of the simple, and extremely useful 1802 program code instructions. To aid in these explanations, an arbitrary first music Byte of B9, (a high octave G, 3/16-note long) has been placed in address 50, the address of the first note of a melody. The 1802 register locations are variously referenced as R-1.0, low-C, high-B, Register-F, etc.

Initial Parameters

Register-8 is firstly made the stack pointer. Next,address 50 is loaded into low-8. The speed modifier address, 43, is then loaded into low-9. The LDXA instruction then extracts the contents of address 50, (which in the example is Music Byte B9), and puts it in the D-accumulator. The PLO A instruction then stores this B9 in low-A. With a Music Byte of 00 put at the end of a melody, the program branches back to address 01, and repeats the whole melody. This will continue, until a 'Halt' command stops the program.

Duration Constant

This is obtained by ANDing 70 with the Music Byte. This masks out both the octave bit, and the note bits, leaving the duration byte, 30. As this is stored in high-B, the complete constant is 30 00. This is equivalent to a decimal number of 3 x 16 x 16 x 16 = 12,288.

This constant is later used in the duration loop, where it will be decremented, while the Q-output is oscillating at the note frequency, until hi-B gets to zero. This gives the note's duration.

Speed Modifier

As written, with NOP's from address 0E to 16, the speed of the melody is based on the timing the 'composer' puts into each Music Byte, and remains unaltered. Later, it will be shown how to modify the overall speed of the melody, either up or down, by editing some or all of these nine address locations.

Note Constant

The note bits are firstly extracted from the Music byte by ANDing it with 0F. This masks out the duration bits and the octave bit, leaving a note constant of 09. This constant is then OR'd with 40, which produces the address of the note's frequency constant, associated with the particular note itself. Here, 09 OR'd with 40 gives 49, the address in which the frequency constant for note G had been previously inserted. The LDN instruction gets this frequency constant, 33 (or decimal 51); PLO E stores it in low-E.

(Note that by ANDing with 40, all reference notes used in the program are located within addresses 40 through 4F).

Octave Constant

The Music Byte is again retrieved by GLO A, and AND'd with 80. This masks out the note and duration bits, and in our example, leaves a '1' in the octave bit. This gives an octave constant of 10. (If a low octave note had been programmed instead, a 00 would have resulted, which would cause the high octave generator to be bypassed.) However it is needed in our example, so the frequency constant is retrieved, and a Shift Right, SHR, is made. This divides 33 (or decimal 51) by two. This produces 19 (or decimal 25), also DF = 1 , (a remainder). Then a '1' is subtracted from the D-register, which is then saved as 18 in low-E. This gives a truer pitch for the high octave notes.

Timing Loops

It can now be seen that Q switches on and off, at a rate set by the initial low-E, and a duration set by the initial high-F.

Duration, or Speed Modifier

The overall speed of the melody may be too fast or too slow for the melody programmed in. However, a simple change of speed can be made, by modifying the program at address 0E to either SHR or SHL. These two instructions take the contents of the D-accumulator, (in our example, Hex 30), and shift the binary digits one place to the right, or the left, as desired. Thus:

30 = 0011 0000 (count=48); after SHR, 0001 1000 = 18 (count=24)
30 = 0011 0000 (count=48); after SHL, 0110 0000 = 60 (count=96)

If either instruction is used, followed by a save instruction PHI B at address at 0F, the duration constant, and hence the melody speed, will be either doubled or halved, as applicable.

One of the other two alternate speeds can also be programmed into the same addresses. One of these multiplies the original duration constant in register-B by 1.5, and the other by 0.75. Addresses 04 to 06, plus 43, are programmed to temporarily designate register-9 as a stack pointer, only during this speed modifier. The four modifiers are shown in Table 3. An explanation follows of the 0.75 duration modifier, with Hex 30 being the original contents of high-B:

Memory
Location
Half
Duration
Double
Duration
3/4 x
Duration
3/2 x
Duration
0E F6 (SHR) FE (SHL) FE (SHL) FE
0F BB (PHI B) BB 59 (STR 9) 59
10 C4 C4 E9 (SEX 9) E9
11 C4 C4 9B (GHI B) 9B
12 C4 C4 F6 (SHR) F6
13 C4 C4 F5 (SD) F5
14 C4 C4 F6 (SHR) C4 (NOP)
15 C4 C4 BB (PHI B) BB
16 C4 C4 E8 (SEX 8) E8
Table 3

FE doubles the 30 to 60
59 stores this 60 at address 43
E9 sets X to 9, making register-9 a temporary stack pointer
9B retrieves the original counter of 30
F6 halves the 30, giving Hex-18
F5 subtracts this 18 from 60 in address 43, giving Hex-48
F6 halves the 48, giving 24
BB stores this modified duration constant back in high-B
E8 resets the stack pointer to 8, for the next Music Byte

Thus, the original duration counter of 30 (or decimal 48), has been changed to 24 (or decimal 36), which is 0.75 times its original value. This means that every duration of note or rest will be lowered, giving an overall speed increase of 4/3 times.

Melody Programming

Now comes the interesting task of programming melodies of one's own choice, and then being able to sit back and listen to them, or accompany them on a guitar, or piano, etc.

In Figure 2, the two lines of notes show both octaves that are programmable by the Music Machine. The two lines are prefixed by a symbol called the G-clef. This represents the upper clef of written music, in which most melodies, often with accompanying words, are written. The pitch, or frequency of the notes, is coded by the same Hex-digit, for either the high or low octave note. If a rest (or pause) needs coding, this lower Hex-digit is always coded as a zero. To differentiate between these two octaves, a '1' in bit-8 of the Music Byte changes the frequency to a high octave note.

Music notation and hex codes.
Figure 2

Note: a half note, called a minim, is split between two music bytes. A dotted minim needs three music bytes. A whole note, called a breve, needs four music bytes.

The two octaves of notes shown in Figure 2 have all been coded with a duration of '4', for a 1/4-note, (a crotchet). Below these notes is a summary of the left-hand Hex-digit options; the only difference between the two rows being, of course, the fact that the high-octave digits are decimal-8 greater than the low-octave digits. This is due to the octave-bit of '1' in the highest bit of the Music Byte.

Example.
Figure 3

Figure 3 shows a simple ending to a tune. It is written in the key of C, in 6:8 time. This timing means the equivalent of 6 notes to a bar, each being 1/8 of a whole note in duration. The tune could have been written twice as fast, using a B and 3, instead of E and 6, and a 1 instead of 2, in the first Hex-digit. Note that the sixth note has a new accidental after it, called a 'natural'. It cancels the G# in the same bar, and the note reverts back to G-natural, or just G.

For longer melodies, one of the Speed Modifiers would be put in addresses 0E to 16, as a much easier way to adjust the speed of the melody. Note that the two rests, of duration 4/16 and 2/16, are combined as duration 6/16, to save precious memory space.

Melody No.2

The following melody is part of a well known tango. It has been written directly in Hex-code, and should be recognized by almost everyone:

46 2D 40 26 2D 40 26 2D 27 AA 60 46 2D 40 26 2D 40 26 2D 29 A4 60 46 2D 40 26 2D 40 26 2D 27 AA 60 C4 29 40 A6 AD AC 20 94 9A 29 20 4D 29 20 00

Without going any further into music theory, the few introductions into basic music given herein, should be enough to enable a microprocessor experimenter to transcribe a favorite melody into Music Bytes. A musician friend could give assistance, if difficulties are encountered in early attempts at transcription.

Hardware Considerations

To hear the melody, the output at the Q-output port must be made audible. A simple way of achieving this is to connect a short wire to the Q-output, and bring the wire close to the antenna of an A.M. radio. As long as the 1802-chip clock frequency lies in the range of, say, 750kHz to 1600kHz, the radio can be tuned to the clock frequency, and the melody can be heard.

In the author's system, the original 1MHz clock frequency had been increased by installing a 2.01MHz crystal. This simple change enabled reasonably accurate high frequency notes to be generated by the Music Machine. With this crystal, the low-octave note A is about 220Hz, and the high-octave G# is about 784Hz. These frequencies, and all the intermediate ones, have been made as close as possible to those of a properly tuned piano. To accommodate the higher clock frequency, a simple audio 1-transistor amplifier was used, as shown in Figure 4. Any transistor of Beta >= 50 is O.K. The speaker can be 8 ohms or higher. A ratio of 20:1 for T1 works well.

Speaker output circuits.
Figure 4

However, the use of a 1MHz clock frequency will not affect the operation of the program. The basic difference will be that the note's frequencies will be halved, and their durations will be doubled. The notes will still be in tune, except that they would be one octave lower than with a 2.01MHz clock frequency. The speed difference can be adjusted, as desired, by using a speed modifier.

Derivation of the Frequency Constants

Each instruction in the loops shown in Figure 5 takes a total of 16 machine cycles to complete. To program the Q-output to switch ON and OFF at a specific frequency of 'P' Hz, a frequency constant 'Y' must be derived. This is a decimal constant, whose equivalent in Hex-code is put in low-E. The D-accumulator will be decremented Y-times in the inner loop 'X'.

Loop walk-through.
Figure 5

So, low-E = Y, and let K = clock frequency in MHz. Then t = time of 16 machine cycles, or 16/K. Analysis of the overall loop gives:

Time Q is switched on = t + 3t + 3tY + 4t = 8t + 3tY
Time Q is switched off = t + 3t + 3tY + 4t = 8t + 3tY
Time of 1 Q-On/Off cycle = T usec = 16t + 6tY

This gives T = t(16 + 6Y).

But, T = 10^6/P usec, where P = note frequency in Hz.

So 10^6/P = t(16 + 6Y), or 6Y = 10^6/tP - 16, or Y = 10^6/6tP - 8/3.

Substituting t = 16/K, then, we find Y = 10^6K/96P - 2.67.

Example:

Assume K = 2.01MHz; find Y for low-octave G of 392 Hz.

Then Y = (2.01 x 10^6) / (96 x 392) - 2.67 = 50.7 (or 51 as a whole number).

Converting to hex, Y = 33 hexadecimal.

The constant 33 is loaded in address 49 as the frequency constant for low-octave G of 392 Hz. Similar constants can be derived for any clock frequency or any note frequency.

(The actual note frequencies were obtained from: "Reference Data for Radio Engineers", by IT&T Corp.)

Derivation of the Duration Constants

A duration constant of 30 00 in Register-F will be decremented 3 x 16 x 16 x 16 times, to 00 00. In our case, we only need high-F to reach zero.

To get high-F to 00, number of decrements = 12288 - 255 = 12033.

During 1-cycle of low-octave-G, the D-accumulator is decremented to zero twice, giving 2 x 51 or 102 decrements.

Now, every time D-accumulator is decremented, so is Register-F.

So, high-F lets Q cycle at 392Hz, or: 12033 / 102 = 117.97 (= 118 times).

But, one cycle of a G of 392Hz is 10^6 / 392 = 2551 usec.

So, duration 30 is equivalent to 118 x 2551 usec = .301 sec.

Similar calculations show that duration:
10 = .10 sec
20 = .20 sec
40 = .41 sec
60 = .61 sec

Check:

Melody No. 2, shown earlier, has the equivalent of 32 1/4-notes in it, each of Hex-duration 40. When played through five times for a total of 160 1/4-notes, the total time taken was 65 seconds.

This gave a duration for '40' time of 65/160 or 0.41 seconds. Thus, the theory agreed with practice.

Other Uses

Another use for this program, with two minor modifications, is to employ it as an audio sweep generator. For this purpose, the codes at addresses 2A, 2C, 2F, 42 and 50 are used. The two modifications are:

In the first Music Byte address of 50, a "Sweep Byte" of 22 is inserted as a first attempt. If the program is now run, it will be seen that 22 is put in low-A; low-B becomes 20; low-C is 02; low-D is 42, (which makes low-E a value of FF from address 42). This low-E of FF is decremented to FE at address 2A, ( or decimal 254). After copying to low-F, the frequency and duration loops are picked up, letting the Q-output oscillate at 81.68 Hz for about 0.2 seconds. The program then branches back to address 2A, where low-E is again decremented, dropping to FD, or decimal 253. This allows Q to oscillate at 82.00 Hz for the next 0.2 seconds. The process repeats, with low-E dropping and the frequency increasing, until low-E reaches 01. Then, the next decrement changes it to 00, and the sweep starts up again at the low frequency. With the author's 2.01 MHz clock frequency, the highest frequency obtainable is about 9 kHz.

It can be seen that as the frequency gets higher, the steps between notes become more apparent, as low-E gets smaller and smaller. That is to say, a decrement of 01 when low-E is 250, only varies the frequency by about 0.4%. However when low-E changes from 9 to 8, a frequency change of about 10% occurs.

With the "Sweep Byte" of 22 in address 50, the total duration for one complete sweep is about 52 seconds. Any "Sweep Byte" from 12 to 72 may be put in address 50; (it must end in a 2). The sweep duration can thus be programmed to last from about 26 secs. to over 3 minutes, The Speed Modifiers of doubling or halving the duration can also be brought into play, if desired.

A possible practical use of this sweep generator is in the testing of a complete audio system. With an oscilloscope on the output of the amplifier, the response to the square-wave output from the Q-port can be examined. With a loudspeaker on the amplifier output, resonances, particularly at the lower frequencies, can be detected.

In conclusion, it is felt that this reasonably simple program will stimulate experimenters to work out further modifications.

00      E8          SEX   8          Use Register-8 as stack ptr.
01      F8 50       LDI  50          1st Music Byte loc'n to R-8.0
03      A8          PLO   8
04      F8 43       LDI  43          Speed modifier loc'n to R-9.0
06      A9          PLO   9
07      72          LDXA             Get music byte; advance stk ptr.
08      AA          PLO   A          Store Music Byte in R-A.0
09      32 01       BZ   01          If Music Byte is 00, repeat tune
0B      FA 70       ANI  70          AND 70 with B9
0D      BB          PHI   B          Store result - duration byte

0E-16   All C4      NOP              (See text for speed modifier)

17      8A          GLO   A          Get Music Byte
18      FA 0F       ANI  0F          AND 0F with B9
1A      AC          PLO   C          Store result-note constant = 09
1B      F9 40       ORI  40          OR 40 with 09
1D      AD          PLO   D          Store result-note loc'n = 49
1E      0D          LDN              Get freq. constant in locn'n 49
1F      AE          PLO   E          Store note freq. constant = 33
20      8A          GLO   A          Get Music Byte
21      FA 80       ANI  80          AND 80 with B9; oct. byte = 10
23      32 2A       BZ   2A          If oct. byte is 00, go to 2A
25      8E          GLO   E          Get low oct. freq. constant
26      F6          SHR              Shift rt., nominally halves 'E'
27      FF 01       SMI  01          Final hi-oct. freq. constant mod'n
29      AE          PLO   E          Store hi-oct. freq. constant
2A      C4          NOP              Spare (See "New Uses")
2B      9B          GHI   B          Get duration constant
2C      BF          PHI   F          Make a copy. (See "New Uses")
2D      9F          GHI   F          Get duration constant
2E      32 04       BZ   04          If hi-F=00, get next Music Byte
30      8E          GLO   E          Get frequency constant
31      FF 01       SMI  01          Decrement freq. const; hold in 'D'
33      2F          DEC   F          Decrement duration constant
34      3A 31       BNZ  31          Back through loop until 'D' = 0
36      8C          GLO   C          Get note constant
37      32 2D       BZ   2D          If 00, back through duration loop
39      31 3E       BQ               If Q = 1, go to reset Q
3B      7B          SEQ              Set Q
3C      30 2D       BR   2D          Loop back until duration ends
3E      7A          REQ              Reset Q
3F      30 2D       BR   2D          Loop back until dur'n ends
41      C4          NOP              Spare; end of main program
42      FF                           (See "New Uses")
43      C4          NOP              Reserved loc'n for speed mod'r

        (Note constants; numbers are for author's system,
         #s in parentheses are for colorburst/2 crystal)
44      57 (4D)                      A# (or B-flat)
45      49 (41)                      C# (or D-flat)
46      41 (3A)                      D# (or E-flat)
47      36 (30)                      F# (or G-flat)
48      30 (2B)                      G# (or A-flat)
49      33 (2D)                      G
4A      5C (52)                      A
4B      52 (49)                      B
4C      4D (45)                      C
4D      45 (3D)                      D
4E      3D (36)                      E
4F      39 (33)                      F

50      ...                          1st Music Byte of melody

See Also:


cosmacelf.com

Valid XHTML 1.0!