Audio signal is generated by software and internal MCU
peripherals. There is no dedictated sound controler in PIC
peripherals, but some other resources are used instead. As the
consequence to this compromise, audio output signal is pure binary
(square wave), just like in the old computers and game consoles. To make the sound more
pleasant, there is the passive, first order low-pass RC filter
(R15-R19 and C9). There are five audio channels, each of them
controlled by software. On-off, tone frequency and two-step volume
control is supported. Three channels are typically used for music,
one is for Jack's sound effects and one for his enemies sound
effects.
The most convenient peripheral for audio signal generating is OC
(output Compare), which is preset to Center-Aligned PWM mode.
Unfortunately, there are only four OC channels in PIC24EP512GP202
(or any other 28-pin PIC MCU), and one of them is already used in
horizontal sync generator, so we have only three for audio
application. They are used for music.
The remaining two audio channels (sound effects) are created using TX units from
UART1 and UART2 peripherals. TX buffers (U1TXREG and U2TXREG) are permanently
loaded
with 10101010s, so the whole transmited sequence, including Start
and Stop bits, contains 0101010101s, repeated endlessly. BRG (Baud Rate Generator)
determines the frequency, and On-Off is obtained by remapping
Peripheral Pin Select to TX out or Port Latch.
In the Menu (or Pause) page, each channel is adjusted to Off, Low
and High volume. The only difference which determines volume
level, is OD (Open Drain) bit in ODCx register.
Music (or effect) script contains of 4-byte groups. First byte is
for tone channel #1, then goes tone channel #2, tone channel #3
and duration (in 17.86 ms steps, which is equivqlent to 56 Hz,
same as VGA vertical frequency). The table on the bottom is for
tone pitch bytes (red numbers, 1-75), showing corresponding tones
(blue, A2-B8) and frequencies (black, 110-7920 Hz). If the tone
byte contains 0, it is pause (no tone on that channel), and if it
contains 99, it is "no change" (previous tone continues). All
table members must contain four bytes. Table terminator contains
0,0,0,255 and then follows one-word address (low endian) with new
table which shall be executed. So "0,0,0,255" is opcode "jump" and
the following word is jump address.
For sound effects, script contains 2-byte members. The first one
is the tone pitch, and the second one is pitch in 17.86 ms steps
(56 Hz). Terminator contains two zero bytes. There is no loop
address like in the music script, as sound effects should be
executed only once for each game event. Pause is represented as 0
(followed by pause duration byte which is >0), and there is no
"equal" byte, as this is monotone effects table.
There are two global variables, named
music.shift and
effects.shift, they are used as global
pitch shifters, for final frequency adjustment in one-tone steps.
By default, they are 8
and 6.
respectively.
The first example is for the part of Jumping Jack main theme (pp
is pause and it equals to 00, ee means "equal" and it equals to 99
in the table), and the second one is sound effect for Jack's jump:
.byte
pp,19,38,11
.byte pp,ee,pp,1
.byte
pp,21,38,12
.byte 14,24,41,12
.byte 14,21,ee,12
.byte pp,pp,ee,12
.byte 14,21,ee,23
.byte pp,pp,ee,1
.byte
14,21,38,12
.byte pp,19,ee,12
.byte pp,21,ee,12
.byte pp,24,41,24
.byte pp,19,38,12
.byte pp,21,41,12
.byte pp,24,ee,24
.byte pp,19,43,12
.byte pp,21,42,12
.byte 14,24,ee,12
.byte 14,21,ee,12
.byte pp,pp,ee,12 |
|
.byte 29,2
.byte 30,2
.byte 31,2
.byte 32,1
.byte 33,1
.byte 34,1
.byte 35,1
.byte 36,1
.byte 0,0 |
1 |
A2 |
110 Hz |
13 |
A3 |
220 Hz |
25 |
A4 |
440 Hz |
37 |
A5 |
880 Hz |
49 |
A6 |
1760 Hz |
61 |
A7 |
3520 Hz |
73 |
A8 |
7040 Hz |
2 |
A#2 |
117 Hz |
14 |
A#3 |
233 Hz |
26 |
A#4 |
466 Hz |
38 |
A#5 |
932 Hz |
50 |
A#6 |
1865 Hz |
62 |
A#7 |
3729 Hz |
74 |
A#8 |
7459 Hz |
3 |
B2 |
123 Hz |
15 |
B3 |
245 Hz |
27 |
B4 |
494 Hz |
39 |
B5 |
988 Hz |
51 |
B6 |
1976 Hz |
63 |
B7 |
3951 Hz |
75 |
B8 |
7902 Hz |
4 |
C3 |
130 Hz |
16 |
C4 |
262 Hz |
28 |
C5 |
523 Hz |
40 |
C6 |
1046 Hz |
52 |
C7 |
2093 Hz |
64 |
C8 |
4186 Hz |
|
|
|
5 |
C#3 |
139 Hz |
17 |
C#4 |
279 Hz |
29 |
C#5 |
558 Hz |
41 |
C#6 |
1117 Hz |
53 |
C#7 |
2233 Hz |
65 |
C#8 |
4467 Hz |
|
|
|
6 |
D3 |
147 Hz |
18 |
D4 |
294 Hz |
30 |
D5 |
587 Hz |
42 |
D6 |
1175 Hz |
54 |
D7 |
2349 Hz |
66 |
D8 |
4699 Hz |
|
|
|
7 |
D#3 |
156 Hz |
19 |
D#4 |
311 Hz |
31 |
D#5 |
622 Hz |
43 |
D#6 |
1244 Hz |
55 |
D#7 |
2489 Hz |
67 |
D#8 |
4978 Hz |
|
|
|
8 |
E3 |
165 Hz |
20 |
E4 |
330 Hz |
32 |
E5 |
659 Hz |
44 |
E6 |
1318 Hz |
56 |
E7 |
2637 Hz |
68 |
E8 |
5274 Hz |
|
|
|
9 |
F3 |
175 Hz |
21 |
F4 |
349 Hz |
33 |
F5 |
698 Hz |
45 |
F6 |
1397 Hz |
57 |
F7 |
2794 Hz |
69 |
F8 |
5588 Hz |
|
|
|
10 |
F#3 |
185 Hz |
22 |
F#4 |
370 Hz |
34 |
F#5 |
740 Hz |
46 |
F#6 |
1480 Hz |
58 |
F#7 |
2960 Hz |
70 |
F#8 |
5920 Hz |
|
|
|
11 |
G3 |
196 Hz |
23 |
G4 |
392 Hz |
35 |
G5 |
784 Hz |
47 |
G6 |
1568 Hz |
59 |
G7 |
3136 Hz |
71 |
G8 |
6272 Hz |
|
|
|
12 |
G#3 |
208 Hz |
24 |
G#4 |
415 Hz |
36 |
G#5 |
831 Hz |
48 |
G#6 |
1661 Hz |
60 |
G#7 |
3322 Hz |
72 |
G#8 |
6645 Hz |
|
|
|
Note:
Special credits go to Marko Antonić, who made the arrangements for
music and adapted them for this media. Thanks to him, music sounds
suprisingly good, even with this modest hardware.
|