ctrl-alt-Development
Your hotkey to alternative software development
Essential Reading
There are many nice books out there, but a few of them contain such wisdom that I just must mention them here:
VIC-20 Improved Notes Table
Music made with the VIC-20 almost always sounds off tune. I've always accepted that as a fact until I found out that the musical notes table in the reference manual is badly transposed. And so I set out to make a better table.
Reference Manual Table
The following table shows the note values from the reference manual (just the first octave), the expected frequency if the progression would be according to the scales (with the first note being the base frequency), the actual frequency and the error. Anything off more than one percent is highlighted.
| Note | Low | Expected (Hz) | Actual (Hz) | Error % |
|---|---|---|---|---|
| C1 | 135 | 36.083 | 36.083 | 0.000 % |
| C#1 | 143 | 38.229 | 38.661 | 1.129 % |
| D1 | 147 | 40.502 | 40.093 | 1.011 % |
| D#1 | 151 | 42.911 | 41.635 | 2.973 % |
| E1 | 159 | 45.462 | 45.104 | 0.787 % |
| F1 | 163 | 48.165 | 47.065 | 2.284 % |
| F#1 | 167 | 51.030 | 49.205 | 3.576 % |
| G1 | 175 | 54.064 | 54.125 | 0.113 % |
| G#1 | 179 | 57.279 | 56.974 | 0.533 % |
| A1 | 183 | 60.685 | 60.139 | 0.899 % |
| A#1 | 187 | 64.293 | 63.676 | 0.959 % |
| B1 | 191 | 68.116 | 67.656 | 0.675 % |
You can see why any music made using this table will sound off tune ;-)
Improved Tuned Table (PAL)
The following table takes the actual note frequencies (non transposed) and shows the best matching value and error for PAL systems. The given actual and error is for the rightmost value.
| Note | Low | Mid | High | Expected (Hz) | Actual (Hz) | Error % |
|---|---|---|---|---|---|---|
| C#1 | 130 | 34.648 | 34.640 | 0.023 % | ||
| D1 | 137 | 36.708 | 36.695 | 0.036 % | ||
| D#1 | 144 | 38.891 | 39.009 | 0.304 % | ||
| E1 | 150 | 41.203 | 41.238 | 0.084 % | ||
| F1 | 156 | 43.654 | 43.737 | 0.192 % | ||
| F#1 | 161 | 46.249 | 46.064 | 0.401 % | ||
| G1 | 167 | 48.999 | 49.205 | 0.419 % | ||
| G#1 | 172 | 51.913 | 52.169 | 0.492 % | ||
| A1 | 176 | 55.000 | 54.810 | 0.345 % | ||
| A#1 | 181 | 58.270 | 58.514 | 0.417 % | ||
| B1 | 185 | 61.735 | 61.857 | 0.197 % | ||
| C2 | 189 | 65.406 | 65.606 | 0.305 % | ||
| C#2 | 193 | 130 | 69.296 | 69.280 | 0.023 % | |
| D2 | 196 | 137 | 73.416 | 73.390 | 0.036 % | |
| D#2 | 199 | 144 | 77.782 | 78.018 | 0.304 % | |
| E2 | 202 | 150 | 82.407 | 82.476 | 0.084 % | |
| F2 | 205 | 156 | 87.307 | 87.475 | 0.192 % | |
| F#2 | 208 | 161 | 92.499 | 92.128 | 0.401 % | |
| G2 | 211 | 167 | 97.999 | 98.409 | 0.419 % | |
| G#2 | 213 | 172 | 103.826 | 104.337 | 0.492 % | |
| A2 | 216 | 176 | 110.000 | 109.620 | 0.345 % | |
| A#2 | 218 | 181 | 116.541 | 117.027 | 0.417 % | |
| B2 | 220 | 185 | 123.471 | 123.714 | 0.197 % | |
| C3 | 222 | 189 | 130.813 | 131.212 | 0.305 % | |
| C#3 | 224 | 193 | 130 | 138.591 | 138.560 | 0.023 % |
| D3 | 226 | 196 | 137 | 146.832 | 146.780 | 0.036 % |
| D#3 | 227 | 199 | 144 | 155.563 | 156.036 | 0.304 % |
| E3 | 229 | 202 | 150 | 164.814 | 164.952 | 0.084 % |
| F3 | 230 | 205 | 156 | 174.614 | 174.949 | 0.192 % |
| F#3 | 232 | 208 | 161 | 184.997 | 184.255 | 0.401 % |
| G3 | 233 | 211 | 167 | 195.998 | 196.818 | 0.419 % |
| G#3 | 234 | 213 | 172 | 207.652 | 208.675 | 0.492 % |
| A3 | 235 | 216 | 176 | 220.000 | 219.241 | 0.345 % |
| A#3 | 236 | 218 | 181 | 233.082 | 234.054 | 0.417 % |
| B3 | 220 | 185 | 246.942 | 247.429 | 0.197 % | |
| C4 | 222 | 189 | 261.626 | 262.424 | 0.305 % | |
| C#4 | 239 | 224 | 193 | 277.183 | 279.355 | 0.784 % |
| D4 | 240 | 226 | 196 | 293.665 | 293.559 | 0.036 % |
| D#4 | 241 | 227 | 199 | 311.127 | 309.286 | 0.592 % |
| E4 | 242 | 229 | 202 | 329.628 | 326.792 | 0.860 % |
| F4 | 230 | 205 | 349.228 | 346.400 | 0.810 % | |
| F#4 | 243 | 232 | 208 | 369.994 | 368.511 | 0.401 % |
| G4 | 244 | 233 | 211 | 391.995 | 393.636 | 0.419 % |
| G#4 | 234 | 213 | 415.305 | 412.381 | 0.704 % | |
| A4 | 245 | 235 | 216 | 440.000 | 444.103 | 0.932 % |
| A#4 | 236 | 218 | 466.164 | 468.108 | 0.417 % | |
| B4 | 220 | 493.883 | 494.857 | 0.197 % | ||
| C5 | 222 | 523.251 | 524.848 | 0.305 % | ||
| C#5 | 247 | 239 | 224 | 554.365 | 558.710 | 0.784 % |
| D5 | 240 | 226 | 587.329 | 597.241 | 1.688 % | |
| D#5 | 248 | 241 | 227 | 622.254 | 618.571 | 0.592 % |
| E5 | 242 | 229 | 659.255 | 666.154 | 1.046 % | |
| F5 | 230 | 698.456 | 692.800 | 0.810 % | ||
| F#5 | 249 | 243 | 232 | 739.989 | 753.043 | 1.764 % |
| G5 | 244 | 233 | 783.991 | 787.273 | 0.419 % | |
| G#5 | 234 | 830.609 | 824.762 | 0.704 % | ||
| A5 | 250 | 245 | 235 | 880.000 | 866.000 | 1.591 % |
| A#5 | 236 | 932.327 | 911.579 | 2.225 % |
Improved Tuned Table (NTSC)
The following table takes the actual note frequencies (non transposed) and shows the best matching value and error for NTSC systems. The given actual and error is for the rightmost value.
| Note | Low | Mid | High | Expected (Hz) | Actual (Hz) | Error % |
|---|---|---|---|---|---|---|
| C1 | 133 | 32.703 | 32.746 | 0.131 % | ||
| C#1 | 140 | 34.648 | 34.739 | 0.264 % | ||
| D1 | 146 | 36.708 | 36.651 | 0.155 % | ||
| D#1 | 152 | 38.891 | 38.786 | 0.269 % | ||
| E1 | 158 | 41.203 | 41.186 | 0.043 % | ||
| F1 | 163 | 43.654 | 43.424 | 0.526 % | ||
| F#1 | 169 | 46.249 | 46.453 | 0.442 % | ||
| G1 | 173 | 48.999 | 48.720 | 0.571 % | ||
| G#1 | 178 | 51.913 | 51.883 | 0.058 % | ||
| A1 | 182 | 55.000 | 54.726 | 0.498 % | ||
| A#1 | 186 | 58.270 | 57.899 | 0.638 % | ||
| B1 | 190 | 61.735 | 61.462 | 0.444 % | ||
| C2 | 194 | 133 | 65.406 | 65.492 | 0.131 % | |
| C#2 | 197 | 140 | 69.296 | 69.478 | 0.264 % | |
| D2 | 201 | 146 | 73.416 | 73.303 | 0.155 % | |
| D#2 | 204 | 152 | 77.782 | 77.573 | 0.269 % | |
| E2 | 207 | 158 | 82.407 | 82.371 | 0.043 % | |
| F2 | 209 | 163 | 87.307 | 86.848 | 0.526 % | |
| F#2 | 212 | 169 | 92.499 | 92.907 | 0.442 % | |
| G2 | 214 | 173 | 97.999 | 97.439 | 0.571 % | |
| G#2 | 217 | 178 | 103.826 | 103.766 | 0.058 % | |
| A2 | 219 | 182 | 110.000 | 109.452 | 0.498 % | |
| A#2 | 221 | 186 | 116.541 | 115.797 | 0.638 % | |
| B2 | 223 | 190 | 123.471 | 122.923 | 0.444 % | |
| C3 | 224 | 194 | 133 | 130.813 | 130.984 | 0.131 % |
| C#3 | 226 | 197 | 140 | 138.591 | 138.957 | 0.264 % |
| D3 | 228 | 201 | 146 | 146.832 | 146.606 | 0.155 % |
| D#3 | 229 | 204 | 152 | 155.563 | 155.146 | 0.269 % |
| E3 | 231 | 207 | 158 | 164.814 | 164.742 | 0.043 % |
| F3 | 232 | 209 | 163 | 174.614 | 173.696 | 0.526 % |
| F#3 | 233 | 212 | 169 | 184.997 | 185.814 | 0.442 % |
| G3 | 235 | 214 | 173 | 195.998 | 194.878 | 0.571 % |
| G#3 | 236 | 217 | 178 | 207.652 | 207.532 | 0.058 % |
| A3 | 237 | 219 | 182 | 220.000 | 218.904 | 0.498 % |
| A#3 | 238 | 221 | 186 | 233.082 | 231.594 | 0.638 % |
| B3 | 239 | 223 | 190 | 246.942 | 245.846 | 0.444 % |
| C4 | 240 | 224 | 194 | 261.626 | 261.967 | 0.131 % |
| C#4 | 226 | 197 | 277.183 | 275.517 | 0.601 % | |
| D4 | 228 | 201 | 293.665 | 295.926 | 0.770 % | |
| D#4 | 242 | 229 | 204 | 311.127 | 313.333 | 0.709 % |
| E4 | 243 | 231 | 207 | 329.628 | 332.917 | 0.998 % |
| F4 | 232 | 209 | 349.228 | 347.391 | 0.526 % | |
| F#4 | 244 | 233 | 212 | 369.994 | 371.628 | 0.442 % |
| G4 | 245 | 235 | 214 | 391.995 | 389.756 | 0.571 % |
| G#4 | 236 | 217 | 415.305 | 420.526 | 1.257 % | |
| A4 | 246 | 237 | 219 | 440.000 | 443.889 | 0.884 % |
| A#4 | 238 | 221 | 466.164 | 470.000 | 0.823 % | |
| B4 | 247 | 239 | 223 | 493.883 | 499.375 | 1.112 % |
| C5 | 240 | 224 | 523.251 | 515.484 | 1.484 % | |
| C#5 | 226 | 554.365 | 551.034 | 0.601 % | ||
| D5 | 228 | 587.329 | 591.852 | 0.770 % | ||
| D#5 | 242 | 229 | 622.254 | 614.615 | 1.228 % | |
| E5 | 249 | 243 | 231 | 659.255 | 665.833 | 0.998 % |
| F5 | 232 | 698.456 | 694.783 | 0.526 % | ||
| F#5 | 244 | 233 | 739.989 | 726.364 | 1.841 % | |
| G5 | 250 | 245 | 235 | 783.991 | 799.000 | 1.914 % |
| G#5 | 236 | 830.609 | 841.053 | 1.257 % | ||
| A5 | 246 | 237 | 880.000 | 887.778 | 0.884 % | |
| A#5 | 238 | 932.327 | 940.000 | 0.823 % |
Frequency to register value
To calculate the register value for a specific frequency, lets say, 440 Hz (A4), you need to know if you have a PAL or NTSC VIC-20 and also for which channel (HI,MID,LO) you want it.
| PAL | NTSC | |
|---|---|---|
| HI | 17320 | 15980 |
| MID | 8660 | 7990 |
| LO | 4330 | 3995 |
The table can be found in the VIC-20 reference manual on page 217. The values are determined by dividing the Phi2 clock of the VIC.
With this constant you can apply the formula:
value = 255 - (constant / desired frequency)
Since the registers hold only an integer value and the formula procuduces real numbers the rounding introduces an error. To get the best possible accuracy you should pick the channel with the lowest number, but no lower than 128. Values below 128 will clear bit 7 turning the channel off.
In the table below I've calculated the values for 440Hz (A4) and 110Hz (A2). Best values highlighted in bold.
| 440HZ (A4) | 110HZ (A2) | |||
|---|---|---|---|---|
| PAL | NTSC | PAL | NTSC | |
| HI | 216 | 219 | (98) | (110) |
| MID | 235 | 237 | 176 | 182 |
| LO | 245 | 245 | 216 | 219 |