Jump to content

Crispy

Members
  • Posts

    65
  • Joined

  • Last visited

Everything posted by Crispy

  1. Greetings fellow FPGAer, Yes, the 6532 datasheet is ambiguous in places. Hopefully I can clear away some of the fog for you. First off, in order to implement the timer you will need to create logic that uses both phi2 clock edges. In my implementation all of my logic is clocked at 28.63636 MHz, and I use a 2 bit bus to package up two clock enables. One bit serves as the phi2 rising edge, and the other as the phi2 falling edge. You will notice in the timing diagram on page 2-57 that the timer counts on the falling edge of phi2, and that the interrupt flag gets asserted on the rising edge when the counter is equal to 255. So, when writing a 0 to the timer register, the counter will be set to 0 during the write cycle, and then will decrement to 255 on the falling edge of phi2 at the end of the write cycle. The interrupt flag will then be set on the rising edge that immediately follows. Also note that the condition that sets the interrupt flag has priority over a register access, so if the counter is 255 when the interrupt register is accessed, then the interrupt flag will remain set. Also note that the prescaler must be set to 1024T on reset. There are some games that use the timer without actually writing to it first, and will fail to run if the prescaler is not configured correctly on reset. I found this out the hard way. Outside of the new/old register bug, the schematic is accurate, at least to the point that everything I've thrown at my FPGA works as it should. And yes, the timing issue you pointed out threw me at first, but I finally got it sorted out. If you add up all of the delays for a register write, you'll find that it takes the TIA longer than 140ns for the write to be fully decoded and latched into the register. This causes the register write to occur after the falling edge of the osc clock, and so the graphics logic that updates on the falling edge of the osc clock won't see the new value written into the register until one clock later. I introduced a comparable delay in my FPGA design by decoding all cpu writes on the falling edge of the osc clock following the cpu write cycle. Cheers.
  2. Crispy

    Drive!

    Looks good and works well on my hardware. At first I was going to suggest adding some inertia to the steering, but then when the game speed ramped up, I decided that it was better without it.
  3. I ran a couple of simulations of the audio block in my FPGA based 2600 with AUDC = 2 and AUDC = 3, and here's what I saw. AUDC = 2 When AUDC is 2 the bit sequence is indeed 465 bits long, but it's made up of two patterns that are essentially the same. The only differences are in the pulse widths, and the differences are quite small. AUDC = 3 When AUDC is 3, the pattern is more complex, but does have some repetition in it as well. This might explain what you are hearing.
  4. Very cool. Don't get too bogged down in the details concerning what I called deferred writes in my test bench. The important point is that for every call to TIASnd::updateAudioState(), the audf and audc parameters must contain the values that were in AUDF and AUDC at the point in time with which this audio sample is associated. So yes, if a register write happens after the second audio clock cycle on a line, then the value written won't be seen by the audio blocks until the next line, and this applies to all registers.
  5. Easier done than said. unsigned short left; unsigned short right; unsigned short vol_lut[256]; left = vol_lut[aud0_pulse_is_high ? AUDV0 : 0]; right = vol_lut[aud1_pulse_is_high ? AUDV1 : 0];
  6. Yes, this is an excellent point RevEng. Breaking the direct connection between the two audio pins on the TIA will change the sound. While on the subject of stereo sound, I'll throw in a couple of ideas that I had. I was thinking of adding mixed stereo sound to the HDMI interface on my FPGA 2600. It's too late for the analog audio since it's hard wired for mono sound on the PCB, so I would only be able to do this for the HDMI audio. My thought was to define two new TIA registers that would be used to position each audio channel on the stereo output. It would be an 8 bit register, and a 0 would position the channel all the way left, while a 255 would position it all the way right. With this feature a channel could be panned, or placed at any position in the stereo image. Of course this would be a useless feature since it would require games to be written to take advantage of the new feature, and it's unlikely that my FPGA 2600 will become a target platform for game designers. So I had the idea of an add-on board for real 2600 systems. I could create a small PCB that would sandwich in between the main PCB and the TIA (the TIA would be removed from the main board, and plugged into a socket on the add-on board). It would have logic that would decode the new register addresses, and store the values written to these addresses. These values would be then used to control each mixer for each TIA audio channel. It's just a thought.
  7. OK, so I had to try my hand at this. Here's my attempt at getting your code to sound on real hardware like it does on Stella. The idea here is to keep track of the TIA audio clock divider count in order to ensure that writes to AUDF1 don't cause a short or long cycle count. At first I used a variable to count clock cycles during a frame, but then realized that a simpler way to do it is to make the frame length an even multiple of the clock divider count. Because of this, my code generates frames that are 271 lines long. My Sony Bravia TV handles it just fine, but I can't guarantee that all TVs will. In the end, it sounds close, but not exact, and that is due to the differences in the way that the two audio channels are mixed together. phaser06_extra_lines.bin
  8. Oh, ugh, the EVIL C++. Burn it! Burn the witch!
  9. Ah Ha! I was wondering if that was going to trip you up. No, it's not a typo. In my translation from Verilog to C I wanted to keep the C code as true to the Verilog as possible. There are several single bit signals in my Verilog code (mostly the LFSR feedback signals) and I wanted to constrain the values of those signals to 0 and 1 in the C code. Since C doesn't have a boolean datatype that would take care of such things by nature, I was forced to play some tricks. Take the case of (x & 0x04). If bit 2 is set in x, the expression will evaluate to 4, but I want 1 instead. I could achieve this with the expression ((x & 0x04) == 0x04), but I like the compactness of (x & 0x04)&&1. There's another case that may need explanation. Verilog has what is called a reduction operator, and it's really slick. Let's say you have a 5 bit bus that is named my_bus, and you want to create a 1 bit flag that is true when any of the bits in the bus are set. Well, you could write something like this. flag = my_bus[4] | my_bus[3] | my_bus[2] | my_bus[1] | my_bus[0]; But the reduction operator is much nicer. flag = |mybus; The same thing can be achieved in C with the logical AND operator. flag = mybus&&1; So, whenever you see a logical operator in my C code, you can assume that it's being used to promote an integer value to a boolean value. I hope this helps.
  10. I'll have to grab a big bag of Reese's Pieces, and sit down and have another go at it. The ship landing sound is definitely a good test. It sounds like it's using a subtle phasing effect, which apparently is something that is giving emulators trouble. Thanks for the link. Do you know of any other games or demos that are good for demonstrating sound issues?
  11. So out of curiosity, I ran ET on my FPGA 2600, and made a recording of the ship landing sound. Then I played the game for a few seconds, at which point I shut off the power, and deleted it from my Harmony cartridge. ET-MMDC.aiff
  12. Oops! How about that. I just found a bug in my FPGA code. Please use this one instead. MMDC_audio_C_bugfix.zip
  13. Sure, no problem. Feel free to use it. Please use this one though. I renamed a couple of signals with names that make more sense. MMDC_audio_C.zip
  14. I don't have a clear view of the overall architecture of Stella, so I may be missing something, but it looks to me like some of the register writes are being missed during the bulk processing that occurs in the TIASound::process() method. Looking at the while loop at line 177, I don't see any mechanisms inside the loop to change div_n_cnt based on a new value of audf0 or audf1. Anyway, looking at the Stella code made me curious, so I took a detour. I translated my Verilog code more or less directly to C, and wrote a test bench to exercise the logic. Turns out it actually works. I've attached the source code in case you want to see it. The test bench mimics the phaser06.bin ROM, and I've also attached an AIFF file encapsulating the raw data that my code generated. Uhm, I'm not permitted to upload C source files?! OK, I'll zip it up then. MMDC_audio_C.zip phaser06_MMDC_C_code.aiff
  15. You can hear this on Stella, since Stella sounds very close to my original attempt at audio. But, in case you wanted to hear the sound on my hardware, I made a couple of recordings. The Ms-Pacman_MMDC_Analog.aiff clip demonstrates the cross modulation distortion, and the Ms-Pacman_MMDC_Old_HDMI.aiff demonstrates additive mixing, which doesn't have the distortion. Ms-Pacman_MMDC_Analog.aiff Ms-Pacman_MMDC_Old_HDMI.aiff
  16. I looked at the Phaser06 code, and found that it is writing to AUDF1 twice in a frame. On line 237, it sets AUDF1 to 15, and on line 253 sets it to 16. How often is TIASound::process() being called? If it's only once per frame then it's missing the mid frame clock divider changes, and that explains why the effect is not audible. I didn't spend a lot of time looking at the TIASnd code, but I did see one thing that did stand out. Stella implements the clock divider counter with the following code. // Process channel 1 if (div_n_cnt1 > 1) { div_n_cnt1--; } else if (div_n_cnt1 == 1) { process the audio } However, the clock divider logic is implemented in the TIA in the following manner. Note that div_cnt is actually a 5 bit binary counter which by nature increments from 31 to 0. unsigned char div_cnt; if (audio_tick) { if ((div_cnt == AUDF1) || (div_cnt == 31)) div_cnt = 0; else div_cnt += 1; if (div_cnt == AUDF1) update_pulse_generator_state(); } The comparator logic leads to an interesting side effect. If AUDF1 is changed to a value lower than the current count of div_cnt, then div_cnt will continue counting up to 31, and then wrap back to 0. It will then continue counting up to the new value stored in AUDF1 before it triggers a logic update. For example, assume that AUDF1 is 3, and div_cnt is 0. During the time when div_cnt is 2, we set AUDF1 = 1. Now, div_cnt will count up to 31, wrap to 0, and then count to 1 before it triggers the next logic update. After that, the clock divider will continue to function as a divide by 2 divider. For a brief time we tricked the divider into dividing by 34, which shouldn't be possible according to the TIA documentation. The same sort of thing is happening in the Phaser06 code, and unless I'm overlooking something, it appears that Stella is not handling it correctly. I'll look a little closer when I have some more time.
  17. You're welcome. I was hoping that someone else besides me would get some use out of it. To answer your question, yes, this demo sounds better, in terms of accuracy, when played through the improved HDMI interface. You can definitely hear the absence of the cross modulation I talked about in my paper when playing it through the old HDMI interface. I've attached a zip file with some recordings I made so that you can compare for yourself. Unfortunately, none of these sound like what I'm hearing from Stella, although I do really like the sound of the effect that Stella produces. I'm not sure what the code in this ROM is doing. I'd have to sit down, and take a look at it. I'm wondering if the difference in sound has something to do with the behavior of the clock divider in Stella. Phaser06.zip
  18. Back when I was developing and testing the HDMI interface for my FPGA based Atari 2600, I noticed some minor, and some major differences in sound between the HDMI digital audio and the analog audio. After giving it some thought, I realized what was causing these differences, and I was able to rework my HDMI interface so that the digital audio sounds exactly like the analog audio. For some reason I felt compelled to document my findings, so I sat down and wrote about it. I was going to put it all down in a post here, but I got carried away, and my paper ended up being eleven pages long. So, instead of creating a monster post, I'll just attach a PDF of my write up. I am also including one of the test programs I wrote while investigating the issue. After reading my article, it will make more sense. This program sets up the audio registers to output a 748 Hz pure tone on one channel, and a 10.6 Hz tone on the other. Hold down the GAME SELECT switch to play the 748 Hz tone, and the GAME RESET switch to play the 10.6 Hz tone. Run this program on Stella, and then on a real 2600, and note the difference. TIA Sounding Off in the Digital Domain.pdf tremolo.bin
  19. 114881 Unfortunately, I still haven't finished adding the screenshot feature to my FPGA, so I had to resort to taking a picture of the TV screen
  20. Simple answer: the triple buffer either drops a frame or repeats a frame every so often depending on how the two timings are beating against each other. Complex answer: I had originally intended to genlock my output vertical timing to the vertical timing from my VCS core. That would produce a nice low latency display without the artifacts of a triple buffer that drops or repeats a frame every so often. But then I discovered that a lot of games out there produce odd or unstable vertical timing, and that is an insurmountable problem. Most modern HDMI televisions have very little tolerance to video timing that veers from the VESA or SMPTE standards that it supports. In fact some television designers are absolute Nazis about it. If the video timing is even a tiny fraction off from the SMPTE or VESA standard, then they consider it an invalid signal, and black out the display. Now, I've designed my triple buffer for the lowest latency possible. with the best case being 5 lines, and worst case 1 frame of latency, but the problem remains that a triple buffer will drop or repeat a frame every so often when the input and output timings differ. That's just the nature of the beast. Of course I could go with a single buffer which would get rid of the frame drops and repeats, but would show a screen tear rolling through the image every so often. I think I would rather live with the effects of the triple buffer.
  21. Yeah, I was kind of worried about odd shaped cartridges, that's why I abandoned my original plan. When I first came up with the idea of the Walkman enclosure, I was going to make it exactly like a Walkman. It was going to have a door that flips open when you press the STOP/EJECT button. You drop the cartridge in, close the door, and then press the PLAY button which causes the cartridge connector to slide in and connect to the cartridge after which the hardware powers up. When you press the STOP/EJECT button it would turn the power off, and disengage the connector. Press the STOP/EJECT button again, and the door flips open. First, the mechanical design for something like that would be complex, but the bigger problem is that it would only work with standard Atari cartridges. So then I had the idea of designing the cartridge slot so that when the cartridge is fully inserted, the end of it would be flush with the edge of the enclosure. Pressing the STOP/EJECT button would then turn off the power, and push the cartridge out. Then I realized that the force required to push the cartridge out would probably be more than plastic parts could handle, so I would have to make the mechanism out of some kind of metal. I arrived at my current design as a sort of compromise. I didn't want the cartridge to stick out too far, because I thought that it wouldn't be visually appealing, but I needed enough of it sticking out to have to something to grab onto in order to remove the cartridge. It was at that point when I considered maybe making some kind of extender/adapter cartridge that puts a connector out close to the end of the enclosure so that odd shaped cartridges would plug in. OK, that's enough rambling for now. Yes, I have a Harmony cartridge, and it works perfect. In fact, I'm pleased that every cartridge and every game that I've tried works. Even the game "Meltdown", which breaks on emulators, works fine on my hardware. That makes me a happy boy.
  22. At one point I considered maybe producing and selling these, but then reality slapped me in the face when I started getting quotes for having the various bits and pieces manufactured. To be honest I really don't want to say what it cost me to have this one-off prototype manufactured, but I'll give you a hint. It was more than the price of an iPad Pro. Since the question came up, I became curious about what it would cost produce these in quantity, so I did some calculations based on some probably wildly inaccurate guestimates, and came of with the following. If I were to do a production run of 100 units, then the retail price would be $769.50 per unit. For a run of 1000 units, the retail price would be $384.75 per unit. The retail price includes what I think is a fair markup over the manufacturing cost. So here's the problem. I could probably find 100 people who would want to buy one of these, but probably none of them would want to pay the $770 retail price. Interesting side note here: this retail price is almost exactly the same as the retail price adjusted for inflation of the Atari VCS when it was released in 1977. The problem is even worse when trying to make a case for a production run of 1000 units. The market probably isn't that big, so I wouldn't be able to sell all of them, and would end up losing a lot of money. Then there are the legal issues to contend with. I remember reading somewhere that Atari holds a number of patents related to the architecture of the TIA chip. Even if those patents have expired, Atari probably still has some ownership of the rights to the intellectual property. I doubt if they would just let me sell these without them getting a piece of the action. Of course if someone comes up with a business plan that would allow us to market my product for a price that people would be willing to pay, then I'm certainly open to that.
  23. I tried the build of Anguna that you posted on 1/19/16, and found no problems with it on my FPGA 2600 or my Atari 2600 Jr. / Sony Bravia flat panel setup. So, out of curiosity I pulled some signals out of the TIA, and put them on the test header on my FPGA 2600. I found that your vertical sync is stable, but your vertical back porch jitters wildly during gameplay (it's stable while the splash screen is displayed though.) Take a look at this video that captures the scope waveforms. The yellow trace is the vertical sync pulse, and the blue trace is the inverted BLANK signal pulled out to the test header from inside the TIA. During the first five seconds of the video, the game is on the splash screen, and you can see that the back porch is stable. Then when I started playing the game at the 5 second mark, you can see that the back porch becomes very unstable. At 11 seconds into the video, I changed the scope setting to zoom in a bit. Counting the horizontal timing at the end of the back porch, you can see that the back porch is changing by as much as 8 horizontal line times. My FPGA 2600 tolerates this, because it uses a counter to wait a fixed amount of time after the vertical sync pulse before it starts using the data from the TIA as active video. I suspect that my 40 inch Sony Bravia flat panel tolerates your timing for similar reasons. But, there are a lot of TVs out there that rely exclusively on the composite signal, and will choke on what you're feeding them. To arrive at a conclusion, I believe that your problem will go away if you write your code so that it maintains a constant number of horizontal line times after the vertical sync pulse before turning off the blanking bit in the VBLANK register.
  24. Good eye. Yes, they are recessed a bit too far. I had designed the PCB and enclosure so that the ends of the switches would stick out about 20 mils when the part is centered on its footprint. The switch leads are much smaller than the holes on the PCB, and I must have positioned the switches too far back when I soldered them on the board. I would take it apart, and reposition the switches, but I'm in the process of making some design changes to the enclosure, one of which is adding a 20 mil chamfer to all of the switch cutout edges. That is a good question. The cartridge well is 2.65 inches long, and was designed so that 1.2 inches of a standard Atari cartridge would be exposed when the cart is fully inserted. This, I thought, was enough to grab onto in order to make it easy to remove the cartridge. Do you have the dimensions for the supercharger and xonox cartridges? That's an interesting idea. Currently, the fast forward button is used as the Game Select switch, and the rewind button for the Game Reset switch while the game is not paused. When the game is paused, then the fast forward and rewind buttons are used to control an OSD menu that allows the user to do things like change the HDMI output format, adjust the VCS vertical size and centering, and turn on and select test patterns. I'm sure I could purpose the buttons for additional functions as well.
  25. I can answer that question now. See this post: http://atariage.com/forums/topic/248199-my-pet-project/
×
×
  • Create New...