johnnye79
-
Content Count
9 -
Joined
-
Last visited
Posts posted by johnnye79
-
-
I'm all about sound, but unsure what you are trying to do.
There is the detailed operation above of what the hardware is doing to produce sound.
That results in the 319 tones and noises you can use in the 2 channel output for notes and percussion.
That's my business mate.

Kidding.
It would be great to know in making a ***NON-COMMERCIAL*** open source VSTi (translated: I'm here for the good of the community), also some hardware projects I'm doing with embedded microcontrollers (STM32 NUCLEO F103RB for example) for neat sound effects, playing music, etc. I understand TIATracker exists, but TIATracker looks like it's for playing music on an Atari cart. Plus, I like to learn things, plus, there's a lot of practical applications I can think of right now for various projects.
I want to get Atari notes in tune with normal piano frequencies by changing the pitch/speed to get them in tune (this can be done procedurally in OpenAL just by changing pitch parameters on a looping sample (1.0 plays at normal frequency, 1.054467467 plays higher, 0.9543954 plays lower, etc), trying to do it with a wav file in Audacity though seems to only go to 3 decimal places).
So far I've used a pitch detection plugin in Audacity to detect the pitches, it uses a YIN algorithm (the plugin is written in Nyquist so a lot is left behind the scenes, I'm looking at a pure C/C++ implementation), and I'm not 100% sure of its accuracy. There are other pitch detection algorithms I'll probably have to look at to determine the best one.
In your picture above what was the method used to determine how many cents a note is off? Is there a mathematical method to it or is that all done by ear? (I'm not implying that one method is better than the other, after all, it all comes down to what sounds pleasing to the ear.)
Why are some of the instruments missing in the above picture? (2, 3, 8, those are some of the best Atari instruments!)
Last bit is trying to figure out how to make a 31400Hz clock in C++ for mbed for audio output, which has proven a little cumbersome since you only get up to microsecond resolution, so I'll have to figure out a clock based on CPU cycles (I have some 72Mhz and 180Mhz STM32s), but that's a side issue.
-
These are the frequencies I analyzed based on a Pitch Detection plugin for Audacity written in Nyquist. I don't know enough yet about Nyquist to see where in the code it's rounding off and truncating frequencies. Clearly it's rounding to the nearest Hz. I wonder if there's a better way to figure it out? I'd like to know those exact frequencies so I know how detuned an instrument is.
const float *startingFrequencies[15] = { 400.0f, // Sample 01 13.0f, // Sample 02 172.0f, // Sample 03 616.0f, // Sample 04 616.0f, // Sample 05 39.0f, // Sample 06 39.0f, // Sample 07 592.0f, // Sample 08 405.0f, // Sample 09 39.0f, // Sample 10 0.0f, // Sample 11 200.0f, // Sample 12 200.0f, // Sample 13 12.0f, // Sample 14 405.0f // Sample 15 }; -
I'm learning about the Atari 2600's sound and have some questions regarding frequency, it has to do with shifting pitches.
How do I obtain the fundamental frequency of a note from the Atari 2600 that's sampled at 31400Hz, with a frequency (AUDF) divisor of 25 for each instrument so that I can shift them in pitch to piano notes?
(This is understandably a mix of programming, mathematics, and music theory, so I'm posting it here.)
So I've sampled small 8-bit Mono WAV files for each instrument (sampled at 31400Hz) with a divisor of 25 at their repetitions. So for example since instrument 8 has a repetition every 511 runs, I ran my Python code to output a wav of 26*511 samples (26 because count goes from 25 to 0) at frequency 25, and I've done this for each sound file so that I get a nice perfectly looping wav file.
My question comes down to how to understand what pitch that sample is at, so that I can shift its pitch to notes that are in tune with piano frequencies. I've tried doing some analysis on the samples in Audacity, but of course see frequency ranges all over the spectrum. So I suppose I need to understand how to attain the fundamental frequency of the sample so that I shift the pitch (this is easily done in OpenAL by specifying a float that determines the multiplier for scaling the pitch).
I've looked at the "Atari 2600 Frequency and Tuning Chart for NTSC" but that only seems to show some information about 5 of the instruments, I'm guessing the whole concept of "Setups" is specific to Paul Slocum's Synthcart, and I'm unsure how they came to the conclusion that a particular note from the 2600 was X number of cents above or below a certain note/octave.
-
I don't think TIA ever worked with any variant of C or Phython. Have you tried ASM?

Stella is written in C you know.

Would be great if Stella would let me put debug watches the AUDXX registers while playing without frame stepping in the debugger. Guess I'll have to mod the source at some point.
The software portion of my project is working at least, just had to set PyAudio to output 16-bit samples instead of 8-bit. (Even though my samples look like they're 8-bit?... O_o) Now to translate it all to a VSTi, there's of course still the issue of frequency translation. (Also turns out that I was smoking crack, instrument 11 is not played on the TIA apparently.)
-
I'm playing around both with emulation code (porting Stella's code to python for testing) and with hardware (I have 2 TIA chips, one from eBay and one that I extracted from a 2600 Jr).
Basically I'd love to write a single channel open source VSTi for the TIA (note: I am not concerned with the $95 Plogue, and right now don't care about emulating the POKEY or any other chipset) that you can plug into your DAW (note: TIATracker does not count, that's a tracker not a VSTi).
(Note: this is also for hobby, fun, learning, and most importantly sharing
)I'd also like to toy around with the hardware on the TIA on one of my actual chips, and have it mostly wired up to my Arduino, but am running into issues and need help.
My Arduino mapping looks like this:
GND to 1 (Vss)
+5V to 20 (Vcc)
Crystal Oscillator output (3.5Mhz) to 11 (OSC)
D2-D7 on Arduino to TIA D0-D5 respectively, writing LSB to D0
A0-A5 on Arduino (writing as digitalWrite outputs) to TIA A0-A5 respectively, writing LSB to A0
D11 on Arduino to RW
D12 on Arduino to Phi-2
+5V to CS2, GND to CS1,CS3,CS4
AUD1/2 to LM386 amp to speakers
When I run it, my speakers make a horrible screaming sound like the sound on Doom 3 when you're going through a teleporter...??
Either my wiring needs to be fixed, my Arduino sketch (included below) needs work...
or I need a young priest, an old priest, some holy water, and some lasers for good measure.
Arduino code:
const unsigned char Sound[2] = {0x15,0x16}; // 4-bit D3-D0: 0 = voice 1, 1111 = voice 16 const unsigned char Freq[2] = {0x17,0x18}; // 5-bit D4-D0: 0 = no division, 11111 = divide by 32 const unsigned char Vol[2] = {0x19,0x1A}; // 4-bit D3-D0: 0 = no output, 1111 = highest // Set RW to Low // Set CS high then low to strobe //const int Ready = 10; const int ClockSync = 11; // Phi-2 on the Atari const int ReadWrite = 12; void setup() { Serial.begin(9600); delay(500); Serial.println("Initializing..."); // put your setup code here, to run once: // data bus pins pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(6,OUTPUT); pinMode(7,OUTPUT); // address pins (set digital) pinMode(A0,OUTPUT); pinMode(A1,OUTPUT); pinMode(A2,OUTPUT); pinMode(A3,OUTPUT); pinMode(A4,OUTPUT); pinMode(A5,OUTPUT); //pinMode(Ready, INPUT); pinMode(ReadWrite, OUTPUT); // This is Phi-2 on the Atari pinMode(ClockSync, OUTPUT); initAtari(); } void initAtari() { digitalWrite(ClockSync, 1); digitalWrite(ReadWrite, 1); delay(100); } void AtariWriteTone(int chan, unsigned char volume, unsigned char freq, unsigned char sound) { digitalWrite(ClockSync, 1); digitalWrite(ReadWrite, 1); delay(200); writeAddressByte(Sound[chan]); writeByteToDataBus(sound); digitalWrite(ClockSync, 0); delay(100); digitalWrite(ReadWrite, 0); delay(200); digitalWrite(ClockSync, 1); digitalWrite(ReadWrite, 1); delay(200); writeAddressByte(Freq[chan]); writeByteToDataBus(freq); digitalWrite(ClockSync, 0); delay(100); digitalWrite(ReadWrite, 0); delay(200); digitalWrite(ClockSync, 1); digitalWrite(ReadWrite, 1); delay(200); writeAddressByte(Vol[chan]); writeByteToDataBus(volume); digitalWrite(ClockSync, 0); delay(100); digitalWrite(ReadWrite, 0); delay(200); } void writeAddressByte(unsigned char data) { int b0 = data & 1; int b1 = (data >> 1) & 1; int b2 = (data >> 2) & 1; int b3 = (data >> 3) & 1; int b4 = (data >> 4) & 1; int b5 = (data >> 5) & 1; digitalWrite(A0,b0); digitalWrite(A1,b1); digitalWrite(A2,b2); digitalWrite(A3,b3); digitalWrite(A4,b4); digitalWrite(A5,b5); } void writeByteToDataBus(unsigned char data) { int b0 = data & 1; int b1 = (data >> 1) & 1; int b2 = (data >> 2) & 1; int b3 = (data >> 3) & 1; int b4 = (data >> 4) & 1; int b5 = (data >> 5) & 1; digitalWrite(2,b0); digitalWrite(3,b1); digitalWrite(4,b2); digitalWrite(5,b3); digitalWrite(6,b4); digitalWrite(7,b5); } void loop() { // put your main code here, to run repeatedly: // int rdy = digitalRead(Ready); //Serial.println("Ready: " + String(rdy)); //delay(1000); for (int voice = 0; voice < 16; voice++ ) { for (int freq = 0; freq < 32; freq++) { Serial.println("Write to Channel 0..."); AtariWriteTone(0,2,freq,voice); //Serial.println("Write to Channel 1..."); //AtariWriteTone(1,2,freq,voice); } } }Now on to the software side. I've been working today on porting Stella's sound code over to Python for testing as kind of a starting point for my VSTi (this is how I learn, don't judge
). It looks like it works, but Instrument 11 (AUDC 0xB) just gives me a high pitched tone on all frequencies. Some of the other instruments I distinctly remember on the VCS being able to go higher frequency. I'm not sure where I'm screwing up here:Python code (yeah I know, pyAudio is nasty, but it's a starting point):
import math import pyaudio import sys import struct from enum import Enum class AUDCxRegister(Enum): SET_TO_1 = 0x00 #0000 POLY4 = 0x01 #0001 DIV31_POLY4 = 0x02 #0010 POLY5_POLY4 = 0x03 #0011 PURE1 = 0x04 #0100 PURE2 = 0x05 #0101 DIV31_PURE = 0x06 #0110 POLY5_2 = 0x07 #0111 POLY9 = 0x08 #1000 POLY5 = 0x09 #1001 DIV31_POLY5 = 0x0a #1010 POLY5_POLY5 = 0x0b #1011 DIV3_PURE = 0x0c #1100 DIV3_PURE2 = 0x0d #1101 DIV93_PURE = 0x0e #1110 POLY5_DIV3 = 0x0f #1111 class AUDFlags(Enum): POLY4_SIZE = 0x000f POLY5_SIZE = 0x001f POLY9_SIZE = 0x01ff DIV3_MASK = 0x0c AUDV_SHIFT = 2 #AUDV_SHIFT = 10 # shift 2 positions for AUDV, # then another 8 for 16-bit sound class TIA: # It made sense to initialize each TIA audio channel as a separate class object # decoupling it from the 2 audio channel coupling of the TIA on the Atari 2600, # so that you could create multiple TIA channels for harmonies such as triad chords. # Structures to hold the 6 tia sound control bytes #myAUDC[2]; // AUDCx (15, 16) #myAUDF[2]; // AUDFx (17, 18) #myAUDV[2]; // AUDVx (19, 1A) myVolume = 0 # Last (final) output volume for each channel myP4 = 0 # Position pointer for the 4-bit POLY array myP5 = 0 # Position pointer for the 5-bit POLY array myP9 = 0 # Position pointer for the 9-bit POLY array myDivNCnt = 0 # Divide by n counter. one for each channel myDivNMax = 0 # Divide by n maximum, one for each channel myDiv3Cnt = 0 # Div 3 counter, used for POLY5_DIV3 mode # ChannelMode myChannelMode; myOutputFrequency = 0 myOutputCounter = 0 myVolumePercentage = 0 Bit4 = [] Bit5 = [] Bit9 = [] Div31 = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] SoundControl = 0 # This takes the place of myAUDCx SoundFrequency = 440 # This takes the place of myAUDFx SoundVolume = 15 # This takes the place of myAUDVx SoundRate = 44100 ################################### def __init__(self): for x in range(0,AUDFlags.POLY4_SIZE): self.Bit4.append(0) for x in range(0,AUDFlags.POLY5_SIZE): self.Bit5.append(0) for x in range(0,AUDFlags.POLY9_SIZE): self.Bit9.append(0) self.reset() ################################### def reset(self): self.polyInit(self.Bit4, 4, 4, 3) self.polyInit(self.Bit5, 5, 5, 3) self.polyInit(self.Bit9, 9, 9, 5) self.myVolume = 0 self.myDivNCnt = 0 self.myDivNMax = 0 self.myDiv3Cnt = 3 self.SoundControl = 0 self.SoundFrequency = 0 self.SoundVolume = 0 self.myP4 = 0 self.myP5 = 0 self.myP9 = 0 self.myOutputCounter = 0 ################################### def polyInit(self, poly, size, f0, f1): mask = (1 << size) - 1 x = mask for i in range(0,mask): bit0 = ( (x >> (size - f0)) if ( size - f0 ) else x ) & 0x01 bit1 = ( (x >> (size - f1)) if ( size - f1 ) else x ) & 0x01 poly[i] = x & 1 # calculate next bit x = ( x >> 1 ) | ( ( bit0 ^ bit1 ) << ( size - 1) ) ################################### def setMasterVolume(self, percent): if (percent <= 100): self.myVolumePercentage = percent ################################### def setOutputFrequency(self, freq): self.myOutputFrequency = freq; ################################### def setChannel(self, address, value): if address == 0: # (usually this would be AUDC0/AUDC1) self.SoundControl = value & 0x0f if address == 1: # (usually this would be AUDF0/AUDF1) self.SoundFrequency = value # (remember that this number is usually divided by 31400Hz) if address == 2: # (usually this would be AUDV0/AUDV1) self.SoundVolume = (value & 0x0f) << AUDFlags.AUDV_SHIFT newVal = 0 # An AUDC value of 0 is a special case if self.SoundControl == AUDCxRegister.SET_TO_1 or self.SoundControl == AUDCxRegister.POLY5_POLY5: # Indicate the clock is zero so no processing will occur, # and set the output to the selected volume newVal = 0 self.myVolume = (self.SoundVolume * self.myVolumePercentage) / 100.0 else: # Otherwise calculate the 'divide by N' value newVal = self.SoundFrequency + 1 # If bits 2 & 3 are set, then multiply the 'div by n' count by 3 if ((self.SoundControl & AUDFlags.DIV3_MASK) == AUDFlags.DIV3_MASK and self.SoundControl != AUDCxRegister.POLY5_DIV3): newVal = newVal * 3 # Only reset those channels that have changed if (newVal != self.myDivNMax): # Reset the divide by n counters self.myDivNMax = newVal # If the channel is now volume only or was volume only, # reset the counter (otherwise let it complete the previous) if ((self.myDivNCnt == 0) or (newVal == 0)): self.myDivNCnt = newVal ################################### def process(self, buffer, samples): bufferPos = 0 # Make temporary local copy audc0 = self.SoundControl p5_0 = self.myP5 div_n_cnt0 = self.myDivNCnt v0 = self.myVolume # Take external volume into account audv0 = (self.SoundVolume * self.myVolumePercentage) / 100 # Loop until the sample buffer is full while(samples > 0): # Process channel 0 if (div_n_cnt0 > 1): div_n_cnt0 -= 1 elif (div_n_cnt0 == 1): prev_bit5 = self.Bit5[p5_0] div_n_cnt0 = self.myDivNMax # The P5 counter has multiple uses, so we increment it here p5_0 += 1 if (p5_0 == AUDFlags.POLY5_SIZE): p5_0 = 0 # Check clock modifier for clock tick if ((audc0 & 0x02) == 0 or ((audc0 & 0x01) == 0 and self.Div31[p5_0] > 0) or ((audc0 & 0x01) == 1 and self.Bit5[p5_0] > 0) or ((audc0 & 0x0f) == AUDCxRegister.POLY5_DIV3 and self.Bit5[p5_0] != prev_bit5)): if (audc0 & 0x04 > 0): # Pure modified clock selected if ((audc0 & 0x0f > 0) == AUDCxRegister.POLY5_DIV3): # POLY5 -> DIV3 mode if ( Bit5[p5_0] != prev_bit5 ): self.myDiv3Cnt -= 1 if ( myDiv3Cnt == 0 ): self.myDiv3Cnt = 3 if (v0 > 0): v0 = 0 else: v0 = audv0 else: # If the output was set turn it off, else turn it on if (v0 > 0): v0 = 0 else: v0 = audv0 elif (audc0 & 0x08 > 0): # Check for p5/p9 if (audc0 == AUDCxRegister.POLY9): # Check for poly9 # Increase the poly9 counter self.myP9 += 1 if (self.myP9 == AUDFlags.POLY9_SIZE): self.myP9 = 0 if (self.Bit9[self.myP9] > 0): v0 = audv0 else: v0 = 0 elif (audc0 & 0x02 > 0): if (v0 > 0 or (audc0 & 0x01 > 0)): v0 = 0 else: v0 = audv0 else: # Must be poly5 if (self.Bit5[p5_0] > 0): v0 = audv0 else: v0 = 0 else: # Poly4 is the only remaining option # Increase the poly4 counter self.myP4 += 1 if (self.myP4 == AUDFlags.POLY4_SIZE): self.myP4 = 0 if (self.Bit4[self.myP4] > 0): v0 = audv0 else: v0 = 0 self.myOutputCounter += self.myOutputFrequency; while((samples > 0) and (self.myOutputCounter >= 31400)): buffer[bufferPos] = v0 bufferPos += 1 self.myOutputCounter -= 31400 samples -= 1 #print("TEST") # Save for next round self.myP5 = p5_0 self.myVolume = v0 self.myDivNCnt = div_n_cnt0 t = TIA() t.setMasterVolume(100) t.setOutputFrequency(44100) t.setChannel(0,int(sys.argv[1])) t.setChannel(2,int(sys.argv[2])) bufferSize = int(sys.argv[3]) direction = int(sys.argv[4]) endBuffer = [] buffer = [] for x in range(0,bufferSize): buffer.append(0) for x in range(0,32): freq = x if direction > 0 else 31-x t.setChannel(1,freq) t.process(buffer,bufferSize) endBuffer.extend(buffer) print("Bit 4") print(t.Bit4) print("Bit 5") print(t.Bit5) print("Bit 9") print(t.Bit9) print("Div 31") print(t.Div31) p = pyaudio.PyAudio() data = endBuffer stream = p.open(format = p.get_format_from_width(1), channels = 1, rate = 44100, output = True) stream.write(struct.pack('f'*len(data), *data)) stream.stop_stream() stream.close() p.terminate()The next question of course is how to scale my waveforms so that I can use any piano frequency, but I'll save that one for after I get things up to a working state at least. My noob brain at Digital Signal Processing is a little fried right now on wrapping my mind around polynomial counters programmatic loops versus traditional waveforms that can expressed with Fourier series transforms and how to translate between the two.

-
CS pins are used to allow more than one memory or I/O IC on the CPU address and data bus. On the 2600 only 2 of the TIA CS are used (/CS0 and /CS3), the other two are just tied to +5V and GND. The 7800 uses 1 more CS pin . If you don't have anything else sharing the same data and address lines with the TIA, then I guess that you can leave it always selected (that is, pin 21,22 and 24 low and 23 high.
But don't take my word for it, as this is beyond my basic skills in electronics.
No worries, thanks for the help you could give, definitely appreciated!

I do have one question. Earlier up there is a picture with some green highlighted parts. Do you know where the full schematic of that image is? Looks like the top is cut off around the oscillator.
Looks very different from another schematic I saw here so I'm curious as to the design of the oscillator (right now I'm using a 3.5Mhz Crystal Oscillator, may change that to 3.579545Mhz crystal with a custom oscillator):
-
TIA outputs are open-collector, so you need to put pullup resistors in order to make them work.
READY (pin 3) is an output used to halt the 6502 until the end of a scanline when the TIA WSYNC register is strobed. Since you're not using the graphics, you probably don't need it in this application.
CSYNC (pin 2) is an output! It's the Composite SYNC for the video signal.
There are 4 CHIP SELECT inputs on the TIA: 3 active-low (pin 21, 22 and 24) and 1 active-high (pin 23). These must be set correctly before accessing the TIA.
EDIT: the picture I was using as reference had 2 of the CS pin active state swapped. I fixed both the picture and the post
Phi0 (pin 4) is an output and it's the clock divided by 3, used as the main clock for the 6502 inside the 2600 console.
Phi2 (pin 26) is an input and it's the phase-2 clock (generated by the 6502 in the 2600). This is used by the TIA to know when valid data can be read/output on the bus, so I'm pretty sure you'll need it to make it work.
Take a look at the timing charts in the Stella Programmer's Guide and in the 650x processor datasheet.
I'd suggest to open a thread in the "hardware" section here on AA, where it's more likely that the electronics experts will see it.
Thanks for the info. I got confused in the Stella docs where it says "when the 02 clock goes high to low" in the Data Addressing section, I thought meant Pin 2.

I've fixed it in my code now to set RW to 1, write my address/data, then set RW to 0. I've added some Pullup resistors to AUD1/AUD2.
Still getting nothing out of the device though (I should add that my speakers also have an internal amp on them, and work very well with my SN76489ANs).
I took a look at the timings in the docs. I'm not sure what to set the 4 CS lines to if I *just* want to use the TIA standalone without the 6507/2 (since I'm using the Arduino to control the TIA). Right now they're floating until I know. Should 21/22/24 be high and 23 be low?
If I'm applying 5V/GND, and an Oscillated 5V to OSC, shouldn't Phi0 be showing some voltage?
My voltmeter shows 0V on 2 different TIA chips (one is out of a working 2600 Jr, and the other was delivered just this week from eBay).
If I'm bypassing the 6507/2, should I be able to write to Phi2 directly? e.g. Set RW to 1 and Phi2 to 0, write address/data, set RW to 0 then Phi2 to 1, as per pages 47 & 48 in the Stella programming guide.
-
I need some noob help, ripping my hair out.
I'm trying to program the TIA's sound from an Arduino and don't seem to be getting anything from AUD1 or AUD2. Also my READY bit is always 0.
On my Arduino I set pins 2-7 to TIA pins D0-D5, and pins A0-A5 to TIA pins A0-A5 respectively (I am writing with digitalWrite on those analog pins from the Arduino, and getting 5V as expected on the right address pins from my Voltmeter).
I have a 3.5Mhz Crystal Oscillator hooked up to OSC on the TIA, 5V/GND to VCC/VSS.
I set R/W to 0, set CSYNC to 1, write my address/data and set CSYNC to 0.
So far no luck, am I missing something?
(I'm not at all concerned with the TIA's graphics or inputs, just the sound, but should I be doing anything on other pins? Do I need to do anything with Phi-0 and Phi-2?)
I've seen some Youtube vids with people circuit bending with the TIA, but haven't seen any specific How To's on the topic, just what I've read from the Stella Programming Guide.
This is my Arduino Sketch just for reference. I used delays rather than waiting on Ready (I know, bad bad bad), but I put in fairly long delays just to test things out, long enough to give lots of cycles.
const unsigned char Sound[2] = {0x15,0x16}; // 4-bit D3-D0: 0 = voice 1, 1111 = voice 16 const unsigned char Freq[2] = {0x17,0x18}; // 5-bit D4-D0: 0 = no division, 11111 = divide by 32 const unsigned char Vol[2] = {0x19,0x1A}; // 4-bit D3-D0: 0 = no output, 1111 = highest // Set RW to Low // Set CS high then low to strobe const int Ready = 10; const int ClockSync = 11; const int ReadWrite = 12; void setup() { Serial.begin(9600); delay(500); Serial.println("Initializing..."); // put your setup code here, to run once: // data bus pins pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(6,OUTPUT); pinMode(7,OUTPUT); // address pins (set digital) pinMode(A0,OUTPUT); pinMode(A1,OUTPUT); pinMode(A2,OUTPUT); pinMode(A3,OUTPUT); pinMode(A4,OUTPUT); pinMode(A5,OUTPUT); pinMode(Ready, INPUT); pinMode(ReadWrite, OUTPUT); pinMode(ClockSync, OUTPUT); initAtari(); Serial.println("Write to Channel 0..."); AtariWriteTone(0,15,14,2); Serial.println("Write to Channel 1..."); AtariWriteTone(1,15,14,2); } void initAtari() { digitalWrite(ReadWrite, 0); digitalWrite(ClockSync, 1); delay(100); } void AtariWriteTone(int chan, unsigned char volume, unsigned char freq, unsigned char sound) { digitalWrite(ClockSync, 1); delay(200); writeAddressByte(Sound[chan]); writeByteToDataBus(sound); digitalWrite(ClockSync, 0); delay(200); digitalWrite(ClockSync, 1); delay(200); writeAddressByte(Freq[chan]); writeByteToDataBus(freq); digitalWrite(ClockSync, 0); delay(200); digitalWrite(ClockSync, 1); delay(200); writeAddressByte(Vol[chan]); writeByteToDataBus(volume); digitalWrite(ClockSync, 0); delay(200); } void writeAddressByte(unsigned char data) { int b0 = data & 1; int b1 = (data >> 1) & 1; int b2 = (data >> 2) & 1; int b3 = (data >> 3) & 1; int b4 = (data >> 4) & 1; int b5 = (data >> 5) & 1; digitalWrite(A0,b0); digitalWrite(A1,b1); digitalWrite(A2,b2); digitalWrite(A3,b3); digitalWrite(A4,b4); digitalWrite(A5,b5); } void writeByteToDataBus(unsigned char data) { int b0 = data & 1; int b1 = (data >> 1) & 1; int b2 = (data >> 2) & 1; int b3 = (data >> 3) & 1; int b4 = (data >> 4) & 1; int b5 = (data >> 5) & 1; digitalWrite(2,b0); digitalWrite(3,b1); digitalWrite(4,b2); digitalWrite(5,b3); digitalWrite(6,b4); digitalWrite(7,b5); } void loop() { // put your main code here, to run repeatedly: int rdy = digitalRead(Ready); Serial.println("Ready: " + String(rdy)); delay(1000); }

"FRYING" and the glitching effects in 2600 games.
in Atari 2600
Posted
You call it frying, I used to call this making Frogger have the weird stage. I would flick the on and off button until the background was like blue instead of black and things like that.