1 #include <stdlib.h>
2 #include <audio.h>
3 #include <bitops.h>
4 #include <clock.h>
5 #include <controller.h>
6 #include <port.h>
7
8 /* Controller definitions */
9 #define INTERNAL_DIVIDER 16
10 #define NUM_CHANNELS 4
11 #define NUM_TONE_CHANNELS 3
12 #define NOISE_CHANNEL 3
13 #define LATCH_DATA_CMD_TYPE 1
14 #define DATA_CMD_TYPE 0
15 #define LATCH_VOLUME_CMD_TYPE 1
16 #define LATCH_TONE_CMD_TYPE 0
17 #define MAX_ATTENUATION 0x0F
18 #define MAX_VOLUME 0xFF
19 #define WHITE_NOISE 1
20 #define PERIODIC_NOISE 0
21 #define TAP_MASK 0x09
22
23 union volume_register {
24 uint8_t raw;
25 struct {
26 uint8_t attenuation:4;
27 uint8_t reserved:4;
28 };
29 };
30
31 union tone_register {
32 uint16_t raw;
33 struct {
34 uint16_t reset_value:10;
35 uint16_t reserved:6;
36 };
37 };
38
39 union noise_register {
40 uint8_t raw;
41 struct {
42 uint8_t shift_rate:2;
43 uint8_t mode:1;
44 uint8_t reserved:5;
45 };
46 };
47
48 struct channel {
49 struct {
50 uint16_t counter:10;
51 uint16_t unused:6;
52 };
53 bool bit;
54 bool output;
55 };
56
57 struct latch_data_cmd {
58 uint8_t data:4;
59 uint8_t type:1;
60 uint8_t channel:2;
61 uint8_t unused:1;
62 };
63
64 struct data_cmd {
65 uint8_t data:6;
66 uint8_t unused:2;
67 };
68
69 union command {
70 uint8_t raw;
71 union {
72 struct {
73 uint8_t contents:7;
74 uint8_t cmd_type:1;
75 };
76 struct latch_data_cmd latch_data_cmd;
77 struct data_cmd data_cmd;
78 };
79 };
80
81 struct sn76489 {
82 union volume_register vol_regs[NUM_CHANNELS];
83 union tone_register tone_regs[NUM_TONE_CHANNELS];
84 union noise_register noise_reg;
85 struct channel channels[NUM_CHANNELS];
86 uint16_t lfsr;
87 uint8_t current_reg_type;
88 uint8_t current_channel;
89 struct port_region region;
90 struct clock clock;
91 };
92
93 static bool sn76489_init(struct controller_instance *instance);
94 static void sn76489_reset(struct controller_instance *instance);
95 static void sn76489_deinit(struct controller_instance *instance);
96 static void sn76489_write(struct sn76489 *sn76489, uint8_t b);
97 static void handle_tone_channel(struct sn76489 *sn76489, int channel);
98 static void handle_noise_channel(struct sn76489 *sn76489);
99 static void mix(struct sn76489 *sn76489);
100 static void sn76489_tick(struct sn76489 *sn76489);
101
102 static struct pops sn76489_pops = {
103 .write = (write_t)sn76489_write
104 };
105
sn76489_write(struct sn76489 * sn76489,uint8_t b)106 void sn76489_write(struct sn76489 *sn76489, uint8_t b)
107 {
108 union command cmd;
109 uint8_t channel;
110
111 /* Fill command parameters */
112 cmd.raw = b;
113
114 /* Handle LATCH/DATA command */
115 if (cmd.cmd_type == LATCH_DATA_CMD_TYPE) {
116 /* Extract channel */
117 channel = cmd.latch_data_cmd.channel;
118
119 /* The 4 data bits are placed into the low 4 bits of the
120 relevant register. For the three-bit noise register, the highest
121 bit is discarded. */
122 if (cmd.latch_data_cmd.type == LATCH_VOLUME_CMD_TYPE)
123 bitops_setb(&sn76489->vol_regs[channel].raw,
124 0,
125 4,
126 cmd.latch_data_cmd.data);
127 else if (channel != NOISE_CHANNEL)
128 bitops_setw(&sn76489->tone_regs[channel].raw,
129 0,
130 4,
131 cmd.latch_data_cmd.data);
132 else
133 bitops_setb(&sn76489->noise_reg.raw,
134 0,
135 3,
136 cmd.latch_data_cmd.data);
137
138 /* Save register type and channel */
139 sn76489->current_reg_type = cmd.latch_data_cmd.type;
140 sn76489->current_channel = channel;
141 }
142
143 /* Handle DATA command */
144 if (cmd.cmd_type == DATA_CMD_TYPE) {
145 /* Get latched channel */
146 channel = sn76489->current_channel;
147
148 /* If the currently latched register is a tone register then the
149 low 6 bits of the byte are placed into the high 6 bits of the
150 latched register. If the currently latched register is a tone
151 register then the low 6 bits of the byte are placed into the
152 high 6 bits of the latched register. */
153 if (sn76489->current_reg_type == LATCH_VOLUME_CMD_TYPE)
154 bitops_setb(&sn76489->vol_regs[channel].raw,
155 0,
156 4,
157 cmd.data_cmd.data);
158 else if (channel != NOISE_CHANNEL)
159 bitops_setw(&sn76489->tone_regs[channel].raw,
160 4,
161 6,
162 cmd.data_cmd.data);
163 else
164 bitops_setb(&sn76489->noise_reg.raw,
165 0,
166 4,
167 cmd.data_cmd.data);
168 }
169
170 /* Reset shift register if needed */
171 if ((sn76489->current_reg_type == LATCH_TONE_CMD_TYPE) &&
172 (channel == NOISE_CHANNEL)) {
173 sn76489->lfsr = 0;
174 bitops_setw(&sn76489->lfsr, 15, 1, 1);
175 }
176 }
177
handle_tone_channel(struct sn76489 * sn76489,int channel)178 void handle_tone_channel(struct sn76489 *sn76489, int channel)
179 {
180 uint16_t counter;
181
182 /* The counter is reset to the value currently in the corresponding
183 register (eg. Tone0 for channel 0). */
184 counter = sn76489->tone_regs[channel].reset_value;
185 sn76489->channels[channel].counter = counter;
186
187 /* If the register value is zero or one then the output is a constant
188 value of +1. This is often used for sample playback. */
189 if ((counter == 0) || (counter == 1)) {
190 sn76489->channels[channel].bit = true;
191 sn76489->channels[channel].output = true;
192 return;
193 }
194
195 /* The output bit is flipped - if it is currently outputting 1, it
196 changes to 0, and vice versa. */
197 sn76489->channels[channel].bit = !sn76489->channels[channel].bit;
198 sn76489->channels[channel].output = sn76489->channels[channel].bit;
199 }
200
handle_noise_channel(struct sn76489 * sn76489)201 void handle_noise_channel(struct sn76489 *sn76489)
202 {
203 struct channel *channel = &sn76489->channels[NOISE_CHANNEL];
204 bool bit;
205
206 /* Reset counter according to the low 2 bits of the noise register */
207 switch (sn76489->noise_reg.shift_rate) {
208 case 0x00:
209 channel->counter = 0x10;
210 break;
211 case 0x01:
212 channel->counter = 0x20;
213 break;
214 case 0x02:
215 channel->counter = 0x40;
216 break;
217 case 0x03:
218 channel->counter = sn76489->tone_regs[2].reset_value;
219 break;
220 }
221
222 /* As with the tone channels, the output bit is toggled between 0 and 1.
223 However, this is not sent to the mixer, but to a "linear feedback shift
224 register" (LFSR), which can generate noise or act as a divider. */
225 channel->bit = !channel->bit;
226
227 /* Handle LFSR only when input changes from 0 to 1 */
228 if (!channel->bit)
229 return;
230
231 /* Handle white or periodic noise depending on mode */
232 if (sn76489->noise_reg.mode == WHITE_NOISE) {
233 /* The input bit is determined by an XOR feedback network.
234 Certain bits are used as inputs to the XOR gates; these are the
235 "tapped" bits. */
236 bit = bitops_parity(sn76489->lfsr & TAP_MASK);
237 } else {
238 /* Bit 0 is tapped (the output bit is also the input bit) */
239 bit = bitops_getw(&sn76489->lfsr, 0, 1);
240 }
241
242 /* Output bit 0 to the mixer */
243 channel->output = bitops_getw(&sn76489->lfsr, 0, 1);
244
245 /* Shift array by one bit and add input bit */
246 sn76489->lfsr >>= 1;
247 bitops_setw(&sn76489->lfsr, 15, 1, bit);
248 }
249
mix(struct sn76489 * sn76489)250 void mix(struct sn76489 *sn76489)
251 {
252 uint8_t vol;
253 uint8_t att;
254 uint8_t final_volume;
255 int channel;
256
257 /* The mixer multiplies each channel's output by the corresponding
258 volume (or, equivalently, applies the corresponding attenuation), and
259 sums them. */
260 final_volume = 0;
261 for (channel = 0; channel < NUM_CHANNELS; channel++) {
262 /* Skip channel if needed */
263 if (!sn76489->channels[channel].output)
264 continue;
265
266 /* Set volume based on attenuation */
267 att = sn76489->vol_regs[channel].attenuation;
268 vol = MAX_VOLUME * (MAX_ATTENUATION - att) / MAX_ATTENUATION;
269
270 /* Add channel output */
271 final_volume += vol / NUM_CHANNELS;
272 };
273
274 /* Enqueue mixer output */
275 audio_enqueue(&final_volume, 1);
276 }
277
sn76489_tick(struct sn76489 * sn76489)278 void sn76489_tick(struct sn76489 *sn76489)
279 {
280 int channel;
281
282 /* Cycle through channels */
283 for (channel = 0; channel < NUM_CHANNELS; channel++) {
284 /* Decrement channel counter if non-zero */
285 if (sn76489->channels[channel].counter > 0)
286 sn76489->channels[channel].counter--;
287
288 /* Skip channel if counter is still non-zero */
289 if (sn76489->channels[channel].counter != 0)
290 continue;
291
292 /* Handle tone channel */
293 if (channel != NOISE_CHANNEL)
294 handle_tone_channel(sn76489, channel);
295 else
296 handle_noise_channel(sn76489);
297 }
298
299 /* Mix all channels */
300 mix(sn76489);
301
302 /* Always consume a single cycle */
303 clock_consume(1);
304 }
305
sn76489_init(struct controller_instance * instance)306 bool sn76489_init(struct controller_instance *instance)
307 {
308 struct sn76489 *sn76489;
309 struct audio_specs audio_specs;
310 struct resource *res;
311
312 /* Allocate SN76489 structure */
313 instance->priv_data = calloc(1, sizeof(struct sn76489));
314 sn76489 = instance->priv_data;
315
316 /* Set up port region */
317 res = resource_get("port",
318 RESOURCE_PORT,
319 instance->resources,
320 instance->num_resources);
321 sn76489->region.area = res;
322 sn76489->region.pops = &sn76489_pops;
323 sn76489->region.data = sn76489;
324 port_region_add(&sn76489->region);
325
326 /* Add clock */
327 res = resource_get("clk",
328 RESOURCE_CLK,
329 instance->resources,
330 instance->num_resources);
331 sn76489->clock.rate = res->data.clk / INTERNAL_DIVIDER;
332 sn76489->clock.data = sn76489;
333 sn76489->clock.tick = (clock_tick_t)sn76489_tick;
334 sn76489->clock.enabled = true;
335 clock_add(&sn76489->clock);
336
337 /* Initialize audio frontend */
338 audio_specs.freq = sn76489->clock.rate;
339 audio_specs.format = AUDIO_FORMAT_U8;
340 audio_specs.channels = 1;
341 if (!audio_init(&audio_specs)) {
342 free(sn76489);
343 return false;
344 }
345
346 return true;
347 }
348
sn76489_reset(struct controller_instance * instance)349 void sn76489_reset(struct controller_instance *instance)
350 {
351 struct sn76489 *sn76489 = instance->priv_data;
352 int channel;
353
354 /* Reset all attenuations and channel counters */
355 for (channel = 0; channel < NUM_CHANNELS; channel++) {
356 sn76489->vol_regs[channel].attenuation = MAX_ATTENUATION;
357 sn76489->channels[channel].counter = 0;
358 }
359 }
360
sn76489_deinit(struct controller_instance * instance)361 void sn76489_deinit(struct controller_instance *instance)
362 {
363 audio_deinit();
364 free(instance->priv_data);
365 }
366
367 CONTROLLER_START(sn76489)
368 .init = sn76489_init,
369 .reset = sn76489_reset,
370 .deinit = sn76489_deinit
371 CONTROLLER_END
372
373