ole00 / libarvid

firmware for Arvid - arcade videocard
2 stars 1 forks source link

Would it be possible to implement some kind of "double strike" display mode? #1

Open asimonf opened 6 years ago

asimonf commented 6 years ago

"double strike" basically refers to outputting a 480i image but not alternating fields between even and odd. This allows a console to be able to switch between interlaced and progressive mode without flickering because no timings would change.

Using double strike is what allows old consoles like the PSX, the SNES and the Saturn to do high resolution menus using 480 lines but be able to switch seamlessly to progressive modes for regular action. You can see this in action when powering up a PSX. The boot up screen is interlaced, but most games switch back to progressive once the boot sequence is done and the transition is seamless.

ole00 commented 6 years ago

If I understand well you'd like to control interlace / non interlace mode on the fly (meaning without changing the video mode itself), just by setting some parameter during rendering. I think that should be possible. The following document explains how to do it: http://martin.hinner.info/vga/pal.html

See the bottom of the page and the Timing paragraph. In order to switch between progressive (current mode in Arvid) to interlace the Vertical synchronisation pulses have to be changed from sequence of 5 x Long + 5x Short syncs for both fields, to alternating between 5xL + 5xS in one field and 1xS + 5xL + 4xS in the other field.

If you look into pruvideo_main.p, there is the Vectical synchronisation defined like this:

// =============================================================
// Frame start
// =============================================================
Frame:
    //Bottom sync seqence -> 6x Sync_A pattern
    call Sync_A
    call Sync_A
    call Sync_A
    call Sync_A
    call Sync_A
    call Sync_A

    //Top sync sequence -> 5x Sync_B, then 5x Sync_A pattern
    call Sync_B
    call Sync_B
    call Sync_B
    call Sync_B
    call Sync_B

    call Sync_A
    call Sync_A
    call Sync_A
    call Sync_A
    call Sync_A

Where Sync_B does the long sync (see, it's called 5x) and Sync_A does the short sync (again called 5x). That corresponds to the progressive mode. If you modify the code to do one frame exactly the same as it does now and the other frame to do A,B,B,B,B,B,A,A,A,A you will get interlaced picture. Then there needs to be a mechanism that allows it to switch these two synchronisation patterns on the fly.

asimonf commented 6 years ago

Hey, amazing. I'm going to try and have a go at it then. Seems uncomplicated enough.

asimonf commented 6 years ago

Sorry to ask you this question here, but I've nowhere else to ask. I haven't been able to source a 74hc4066N locally, and I'm not much of an expert. Given the differences in operating parameters, would a CD4066B be ok as a replacement? I know resistance behaves differently, but I've no idea if that plays a part in the circuit.

Best regards!

ole00 commented 6 years ago

I think it might work. The resistance should be OK, although the Green colour will be a tiny bit suppressed. You can compensate it (raise the Green level) by using higher value of the Green voltage divider resistor (I think on your board it is the 220 Ohm in top left corner) by about 20 to 50 Ohm - if required at all.

The signal propagation delay is bigger on CD4066B (35ns vs. 3ns on 74hc4066N) which may play a part, but there is a fair chance it will work fine. I'd recommend to use an IC socket so you can eventually swap the chip in case it doesn't work. Let me know whether CD4066B works or not.

asimonf commented 5 years ago

Hey @ole00 I've been retaking this project now given that I finally got around to source the parts I needed and expand the circuit to output S/Video and Composite to be able to plug it into my sets.

I've a question. Whenever a call to set the mode is made, I'm seeing that the fbHeight field is being set to the predefined value of 224. Does that mean that the visible part of the screen is always 224 lines regardless of the mode set?

ole00 commented 5 years ago

No, the real 'visible part of the screen' depends on many factors: 1) geometry of your CRT. If you fiddle with pots on the back of the screen you can affect how many scan lines are visible, even though Ardvid draws more scan-lines. You can hide some lines if you stretch the screen too much. 2) total number of scan lines Arvid draws: this is not defined by ap.fbHeight (I might delete the variable actually), it is defined by ap.lines. 3) total number of non-black lines the application draws. If the app (that drives arvid) decides that top 20 and bottom 50 lines will be always black (draws a black pixels there) , then you will actually see only (ap.lines - 20 - 30) lines, because it's hard for the user to distinguish the black lines from the non-drawn lines (top and bottom porch)

In other words: When writing an emulator, at first chose your horizontal resolution (arvid_320 for 320 visible pixels horizontally, arvid_256 for 256 visible pixels horizontally etc. ). Then find out what vertical frequency you need (PAL - 50 frames/sec, NTSC-60 frames/sec etc.). That will determine the number of lines of your videomode. Call arvid_get_video_mode_lines() to get that value. This is the number of scan lines (including top and bottom porches) Arvid will draw. Then you need to decide how many VISIBLE lines you want to display (let's say for Genesis it is 224 lines). By calculating ap.lines - VISIBLE you get the number of lines available for your porches. And you'll need to split this value between top and bottom porch. Your app will need to set the top and bottom part of the frame buffer as black pixels - these are the porches. You can also let the user to 'shift' the picture Up and Down (to better view all lines, different TV display slightly differently) by changing the value of top and bottom porch (the number of black lines on the top and bottom). Please note that many CRTs are not happy if top and bottom porches do not exist, or are too small. In that case you will see distorted image. You have a lot of freedom how to define 'vertical resolution'.
Horizontal resolution is more rigid, it sets the front and back porch depending on the horizontal resolution. Left and right border positions are set by the value set via arvid_set_line_pos().

asimonf commented 5 years ago

I think I may have not explained myself too well. I'm already getting an image of the emulated systems using your libraries. I was just curious as to how you handle the visible and non-visible lines.

In the library, you have this code:

static void init_frame_buffer_(arvid_video_mode mode, int lines, int noFbClear) {
    ap.lines = lines;
    ap.fbWidth = arvid_resolution[mode];
    ap.fbHeight = INITIAL_FB_H;
    //printf("mode set=%i w=%i lines=%i\n", mode, ap.fbWidth, ap.lines);
    ap.fb[0] = (unsigned short*) &ap.ddrMem[16];
    ap.fb[1] = (unsigned short*) &ap.ddrMem[16 + (0x100000 >> 2)]; //4 bytes per int

    if (noFbClear == 0) {
        //clean both frames with black color
        arvid_fill_rect(0, 0, 0, ap.fbWidth, ap.lines, 0);
        arvid_fill_rect(1, 0, 0, ap.fbWidth, ap.lines, 0);
    }
}

Where ap.fbHeight is always set to INITIAL_FB_H which is defined to 224 elsewhere.

I couldn't find the source to arvidmame, so I'm actually curious how you handle the different heights the arcade systems have. Should I send, as part of the blitting process, only the visible part of the image, or should I always send the full height? I guess that's what I'm getting at. Right, now, 224 visible lines works just fine for the SNES 60hz games because the console is always 512x224 unless it's interlaced (I still haven't tackled the double-strike situation on the PRU code).

ole00 commented 5 years ago

I couldn't find the source to arvidmame

https://app.box.com/s/7qy63ht2yy9dsakfu494lar7trw3imzx

how you handle the different heights the arcade systems have

the way I described in my previous response. Height depends on the vertical frequency.

Should I send, as part of the blitting process, only the visible part of the image

yes

Right, now, 224 visible lines works just fine for the SNES 60hz games...

As I wrote earlier, number of lines is stored in variable ap.lines (not ap.fbHeight as you may assume)

asimonf commented 5 years ago

First of all, thank you for your help in this. I know I've asked a lot of questions.

I made my first implementation of double-strike on libarvid. I still need to modify the client and test using an oscilloscope (Need to figure out how to get one). However, I just have one lingering question.

Did you ever figure out how many cycles does it take to read from local data ram from the PRU?

I've this:

lbbo ENABLE_INTERLACE, r0, 0, 2

And I'm reading this is 3 cycles. But I found a comment on your code that implies it could be 4?

ole00 commented 5 years ago

Did you ever figure out how many cycles does it take to read from local data ram from the PRU?

I think it depends how many bytes you read (I might be wrong). In your example it is 2 bytes. When reading 4 bytes it might be more cycles. I forgot the exact cycle values, it was few years back when I did the measurements, and my results might have been incorrect.

And I'm reading this is 3 cycles.

That's not that important for you at this stage. You will only need to read the value once every VSYNC. The difference is only 1 or 2 cycles (5-10ns), so you may only see a tiny glitch on the screen during VSYNC. Once you get the rest of the code working, you can then focus on removing the glitch by changing the timing to compensate for 3 cycle or 4 cycle length of the instruction.

asimonf commented 5 years ago

So I managed to implement it. Or I think I did anyway. The output switches seamlessly. I'm having timing issues, though. The framerate changes. I'm adding one extra line on each field when interlacing is enabled to comply with the docs you sent me but now I hear a bit of crackling on the audio. Will have to figure it out later.

I'm still waiting for my new circuit to arrive because my current one is on a BB and using a composite output means I can't really find any glitches on plain sight.

However, I do have one issue that I'm not sure why it happens. On 50hz it messes up badly as if it lost sync. I don't know if my tv can do 50hz though. 56-61hz works fine.

ole00 commented 5 years ago

Well done. A simple way how to get rid of the crackling noise is to use ground loop isolator. It's a small device (basically just 2 coils with audio jacks, no deed to power it) that you plug in between the audio input and output. You can find it on ebay and aliexpress and elsewhere for $4.

I don't know if my tv can do 50hz though.

Try a different TV. I know, not many people still have CRTs these days. Or maybe a local arcade might help? Or, once you are happy with your code, make it public and I can test the 50 Hz for you if you want.

asimonf commented 5 years ago

Well done. A simple way how to get rid of the crackling noise is to use ground loop isolator. It's a small device (basically just 2 coils with audio jacks, no deed to power it) that you plug in between the audio input and output. You can find it on ebay and aliexpress and elsewhere for $4.

I should have a few lying around. I'll search for them.

Try a different TV. I know, not many people still have CRTs these days. Or maybe a local arcade might help? Or, once you are happy with your code, make it public and I can test the 50 Hz for you if you want.

I'll see what I can find. In any case, the code is public. I made a fork of your projects and added my changes.

asimonf commented 5 years ago

Just to add, I didn't make too many changes in how it currently woks. When interlacing is enabled, instead of sending frames, one should send the individual field to draw. First the even field and then the odd field.

Additionally, I'm missing logic to leave interlaced enabled until a whole frame is drawn if it's disabled after a single field has been sent. It works for my use case, but I might add it at a later date just for completeness.

asimonf commented 5 years ago

Hey there, it's me again :sweat_smile:.

I've been working on a couple new features and I have a few questions. I still need to polish interlacing a bit, but the principle seems to be working so I've set that aside for a bit.

I looked at the PRU video assembly file and managed to make the resolution dynamic. All the constants you define on the specific mode binaries are now sent every frame to the PRU. The purpose is to be able to change them on the fly sort of like how consoles do it. For example, the SNES doesn't have a framebuffer, but it can even change the horizontal resolution per line using interrupts.

Anyway, I'm not interested much in per line seamless resolution switching. I'm much more interested in per-frame resolution switching. Something that both the N64 and the PSX do.

Caveat: I'm looking to implement seamless resolution switching only when the number of lines stays the same (in other words, only when no framerate adjustment happens). Whenever the number lines changes, the code is working just fine.

Sorry for the long intro, but here are my issues.

I've already solved the PRU part of the equation, at least the one pertaining the pruvideo_main file. But if I try to seamlessly switch by simply changing the PRU values required, I get framebuffer corruption unless I stop the frame server and start all over again, defeating the purpose. I figure that this is a race condition, but I haven't been able to understand why.

What's the purpose of the ddrRam pointer in AP?

Is the other PRU still being used?

The other feature I've in the pipeline is to support YPbPr. I already have a proof of concept and my idea is to make the emulator send the YUV data over and modify the circuit to add sync on green.

Edit: Added caveat.

asimonf commented 5 years ago

Finally got it to work. I still think it's a bit finicky, but it seems to be working.

One thing I noticed is that the present implementation of the frame streamer switches framebuffers regardless of if new data has arrived. This produces flicker when the client has not been producing new frames or if the client is too slow. I think I might tackle this next to avoid this flicker, but otherwise, it looks cool.

Another thing that appears to be happening is that frame blitting seems to be taking too long on certain cases. Enough to cut my vsync'd framerate in half from 60 to 30 in a scene with 512x224 pixels. Though I'm just speculating right now, the problem might just be elsewhere.

Sorry to bother you with all of this, it helps me to write it down.

asimonf commented 4 years ago

Hey @ole00, hopefully I can bother you with a few more questions. I've been experimenting with a few ideas that involved a new server I wrote in .NET Core (C just isn't my forte, to be quite honest). For that, I needed to update the base linux OS to Debian 9. I was able to make everything work with the latest kernel 4.9 code (overlay, uio and PRU) but, as you might already know, I got flickering on the screen due to background processes messing things up.

I updated to the latest kernel with RT patches and disabled the most obvious processes but I still couldn't eliminate flickering completely, I got a very slight flickering once or twice every second but I haven't been able to further improve on it. Priority hasn't been particularly helpful either and I'm already on the performance governor. Is there anything else I might be missing?

Cheers!

Another thing, do you, by any chance, still have the code of the PRU streamer?

ole00 commented 4 years ago

Hi, the flickering is not caused by the kernel, it's caused by Linux user-space software that runs on the background - terminals, wifi network programs, dhcp servers and clients, web servers, ssh servers etc. In order to make the smooth Arvid experience you have to uninstall them all one by one. Or generate the rootfs by 'buildroot' system where you can 'uncheck' all of these - it will produce very lean and clean filesystem for you.

Old PRU streamer: it's in git - just checkout the old snapshot. Use something like this:

git checkout a6a22eb5

Use 'git log' to check the commits and their hash-codes.

Then, to go back to the new code use

git checkout master
asimonf commented 4 years ago

Hey man, it's me again. Sorry to bother you again.

I've managed to eliminate wobble while using the streamer by chasing potential stalling (though it's still while drawing a static image), however. I think I messed up the timings somwhere because the image seems a bit ghosty.

How long should a scanline be on your code? Should it be 64 us? Right now I'm clicking it at 62.490 for 320 x 252. I think that due to the fact that I've reduced stalling, drawing now takes less cycles, so I need to tune. Hope you still remember all of this, any help would be appreciated.

Cheers!

ole00 commented 4 years ago

Hi,

How long should a scanline be on your code? Should it be 64 us?

I think that's the value compatible with most of the TVs.

Right now I'm clicking it at 62.490 for 320 x 252.

I think that can still be compatible with CRT TV's although shorter time spent on single scanline makes the whole frame to last shorter time. Therefore the refresh rate will be increased. So if you were aiming at 60Hz, with shorter scanline you might be actually running at 62 Hz which may be an issue for the TV (may cause artifacts).

asimonf commented 4 years ago

I want to thank you for all of your help throughout this. I've been on and off on the project for a while but I think I've managed to achieve everything I set out to do. However, it would have not been possible without your code as a starting base.

I modified the circuit to generate an svideo signal to be compatible with my TVs. I modified it to seamlessly switch horizontal resolutions and interlacing and now I've rewritten the streamer to go back to being PRU based. I fixed the wobble by measuring the stall counter and then by making sure every line was 64usec using the cycle counter register. I even managed to add a line-counted vsync interrupt.

I was able to make an overlay that worked with UIO and was compatible with the latest kernels and latest releases of Debian with the BB in order to be able to use .net core for the server code. It took way longer than I expected

I still need to keep working on the server and client part of my rewrite in c# (switching zlib for zstd has helped so far by allowing me to run higher res games without bottlenecking the 100mbit link), but so far so good.

Here's a pic of the corners using the PRU streamer.

IMG_20200419_160410

I haven't even touched services in Linux so far, so it's looking good.

I may still end up building a new circuit that interfaces directly with the GPIO pins connected to R30 in PPU1 to eliminate any possible contention with the OCP to output pixels, though for that I need to do a small mod in the BB board to route the two missing pins using the JTAG connector. That way, the possibility of any slight wobble is completely eliminated. But I think it's looking good enough so far.

Anyway, thanks again for your help. I will upload the code soon in case you want to take a look, but I still need to clean up a bit.

ole00 commented 4 years ago

It looks quite good, well done!

I fixed the wobble by measuring the stall counter and then by making sure every line was 64usec using the cycle counter register.

Good Idea, when you finish your code I'm interested to look at the implementation. Keep up the good work, It seems you have fun researching and implementing the improvements.

ole00 commented 4 years ago

BTW. I found the (extra) wobbling is also caused / induced by used power supply. I use Arvid on my arcade projects and when I use arcade power supply or PC power supply the wobbling is introduced. If I use notebook power supply (with step down/up voltage converter) or a quality 5V phone charger the wobbling is gone.

asimonf commented 4 years ago

Interesting. I'll have a look at that. I'm powering the device through the mini-usb right now using my display's usb port. I'll change it to a 5v USB charger to see if there's any difference in quality. In any case, it looks pretty good so far for me.

I've been making tests using a PSX-era game (Megaman X6) that switches between interlaced and progressive mode several times during the intro and also uses a 512px wide menu to test out everything and found some interesting things along the way.

With regards to the wobble and flicker. Every now and then (and this is most obvious when running games that use a high number of horizontal pixels like 512 or 640) a single line in a single frame will shift horizontally a bit resulting in a momentary visible tearing. It always shifts right, meaning that, somewhere, the pixel data was delayed. It's very random. Background usage in the OS could have an influence here.

I measured cycle usage again to see if I had messed up something but it doesn't look like that. It could be my TV, but I don't think it is because the image looks very sharp otherwise. I read that GPIO through the OCP can, sometimes, be a bit unprecise (a few cycles here and there) because the BB CPU might be using that interconnect delaying access for a bit for the PRU sybsystem. Given that SBBO instructions are fire and forget, I can't see the flicker reflected in the cycle counter so I think the only alternative is to go through the R30 register directly to the pins to output color data, which is what I'll likely test soon. If you look at the P8 and P9 headers, you'll see that you're missing 2 bits to output through the R30 register in PRU1, but those two pins are connected to the CPU through the serial header (only issue is that there's a buffer in the middle). I only need the one pin and I can test without it too since it's only 1 bit of color missing, it is a PITA, though, because I need to break out the breadboard again. If that fixes it, I'll consider the PRU code finished.

On the software front, the original compression algorithm, zlib, was too slow for decompression, pegging the BB CPU at 100%, and the 100mbit link was saturated with data. I switched to zstd and that gave me some headroom on the ethernet link front in that game but still resulted in the BB CPU being pegged at 100% in the intro of that game, sometimes resulting in missing chunks. Last night, I tested using LZ4 in its HC version and saw BB CPU usage go down from 100% to 60% in said case, but I did see high link usage. If link usage becomes problematic for more modern console modes due to the images having low compressibility, there's always the SanCloud BeagleBone Enhanced with the Gigabit ethernet port. The point is that LZ4 is fast enough to not saturate the CPU in pathological situations like those presented by this game.

All in all, still a bit left to go in order to work out the remaining kinks.

ole00 commented 4 years ago

If 100mbit is limiting you, then perhaps USB2 with 480 mBit could be the answer. I tried ethernet-over-usb on older kernel, but the speed was the limitation. I read that some patches had to be added to make the whole usb system faster on BBB. You mentioned you use more recent kernel, maybe the USB situation changed and the USB speeds are way faster.

Related to memory interconnect: that's true, unfortunately - as you mentioned - SBBO does not give predictable results in respect of clock cycles. I think the only proper solution (cycle exact video signal) is to use FPGA (or FPGA cape for BBB) or trow away BBB and use some specific Video/USB3 chip like FL2000 (primarily VGA output, but can be reprogrammed, source code for drivers are available). Cheap VGA dongles with FL2000 exist. I did some tests and was able to run the Linux kernel driver and output images in VGA resolutions (but not 15kHz).

asimonf commented 4 years ago

With regards to the ethernet speed, I already have a Sancloud Beaglebone Enhanced with the 1 gigabit Ethernet interface, so I use that to test to see if the link is holding me down. Unfortunately, that device has one of the pins of the P8 header disconnected, so that GPIO is unavailable for the blue signal, but speed-wise it works wonderfully. I might try an USB Ethernet device later, after all, I calculate I won't need more than 150mbits, though that could hinder CPU performance.

With regards to the memory interconnect thing, I'm currently trying out direct output mode through R30 on the PRU, which would have deterministic access to the pins (it skips the memory interconnect and outputs directly) and a delay of only one cycle. The only issue that has is that there are only 14 pins available on the headers of the BB connected to R30 on PRU1. However, there's a solution for that. The debug header has two pins, regularly behaving as UART0 TX and RX that can be muxed to be bits 14 and 15 of R30, but of those, only one of them can be used because of the buffer connected to them preventing output. That would mean that bits 0-13 and bit 15 can be used, giving access to the 15-bits of color required for output. The other thing that is required to be able to use that is that the device tree needs to be modified to be able to disable uart0 and reroute debug output to uart1.

I already modified uboot and recompiled it to use uart1 (which could conveniently be rerouted to a new debug header in a cape) and modified the device tree included in the last Debian buster image to use uart1 for output and disable uart0 to be able to mux those pins for PRU usage.

I even modded one of my Beaglebone Greens to remove the uart0 buffer and that way have access to the remainder bit, but that isn't needed. The sync bit can continue to go through the memory interconnect region because it's not a high frequency signal, at 2usec per pulse at the lowest, a few ns here or there won't change the output in any meaningful or visible way. But it can't continue to be the current one, though.

I'm still setting up the breadboard with everything because I need to wire the encoder chip since I don't have a SCART capable TV to be able to see if there's any meaningful improvement in quality. I'll let you know how it goes.

In any case, I still think there's more than enough headroom to continue using the bbone as a platform for the project. If anything, I think that the new beaglebone ai could even become a sbc platform for the project given the CPU resources it has available. At least for simpler systems anyway: without network in the way, proper per-scanline synchronization emulation could even be possible, which would almost eliminate most of input latency from today's emulators due to not having to rely on storing the whole frame on a framebuffer first.

A BeagleBone with an A72 or one of the latest arm CPUs would be my dream SBC for arcade and console retro-emulation. Much more than a cheap FPGA solution due to having much more flexibility with software in general (at least for my abilities anyway).

asimonf commented 4 years ago

I'm starting to believe there's something wrong in my setup that I don't know about.

There's is a slight wobble of the image all the time. To make sure it wasn't my code introducing it, I went and burnt your image into a new sd card and plugged my circuit to the TV and it still wobbles. Unfortunately, I don't have your original circuit at hand because I can't directly plug RGB to my TV but I bought, some time ago, a SCART to Component converter online. I looked inside and it looks like it's mostly just opamps which leads me to believe it's just a colorspace convertion, which is ideal given the circumstances, but I would have to build a new circuit...

I don't know what could possibly be the problem. Maybe I'm too nitpicky, but I don't remember this kind of wobble previously on my Arcade setup. Maybe it's my TV? Maybe there's some interference I haven't been able to remove? I'm at a loss...

I'm going to buy an old console and test that to see if I still notice with that, to see if I can narrow down the source.

ole00 commented 4 years ago

If you can make a video showing the wobbly effect, please make it. I 'll take a look and compare it with mine. I could actually do the same for you, so you'll have some visual reference.

asimonf commented 4 years ago

I tried to capture it on video but it isn't really noticeable. With your software it seems less noticeable than mine, but it could be also that the interference is affected by the image itself being displayed. I'm not sure if my TV is suffering from interference or not, I need to diagnose that first, which is hard for me because I have no other source of analog input for the TV. I really need to get me a console to be able to plug it and test for side-by-side comparisons.

A couple of symptoms:

I'm almost sure that the interference I see in that image is the source of the brightness flicker and the slight wobble I get of the actual images.

I dug up a couple of PCBs I sent to manufacture from your 0.4 version and I think I have the required components, so I'll try to build that and use my SCART to YUV converter to see if noise appears again.

I have a couple of other ideas too. I ordered a few 8-bit and 16-bit bus transceivers for some other projects I have with the beagle bone (a logic analizer) and I also ordered a few RGB DACs (AD7123 and an old DIP AD7120) again, for another project (I also ordered an old pallete 6-bit DAC with an 8-bit bus that I might use for DIY PC/Console I've been working on for a while). All cheapo parts from Aliexpress or Ebay, but they take months to arrive.

I'll first try to see if noise output changes with your circuit, I'll try and use the bus transceiver as a buffer for the GPIO lines comming out of the BB to see if that changes anything when it arrives. Since the circuit will then be exactly the same as yours, it would serve as a more meaningful comparison, though again, I don't have RGB input on my TV. I could mod the RGB input to it, I've done it before, but I'd rather not mess with that.

If that doesn't get me anywhere, I'll actually build a solution with the AD7123 DAC to see if it changes anything afterwards. I'll do that in a universal board (the circuit should be relatively simple since the IC has all of the logic needed for the DAC. If the issue is the DAC, a specially designed DAC for video like the AD7123 should work just fine, though I'm sure my biggest issue is getting an actual, clean, source of 5v power for the analog part of the circuit. Which is where my next step would go to: I've also been trying to buy an oscilloscope and I found an old analog used one a few weeks ago that might fit the bill (it's only 20MHz, though, but it's analog so no aliasing), but I'm in mandatory lockdown right now so unless the parts arrive, I'm going to have to wait.

I only noticed the interference in the first place because I stopped using the composite input for testing. Now it's driving me crazy. I'll continue testing this weekend. Let me know if you're able to record a video showing the wobble to have a reference.

ole00 commented 4 years ago

I took a look a the video, unfortunately I could not see much on it. It's mostly just a black screen, so I can not estimate any wobble effect from it. The best would be to show Arvids's cross hatch pattern with close up on the top left side of the screen where only few rectangles would be visible along with the black border. Hopefully that would show the wobbling effect and other artifacts.

Interference: on my RGB scart setup there's no visible interference nor moire. I get a very clean TV picture even when the circuit is build on breadboard - you can check that on my initial video.

Conversion from RGB to YUV decreases color gamut (colors are dull, or washed out) but should not cause interferences. On the other hand conversion to composite signal often brings color issues - moire patterns on certain screen parts. What I would suggest is to connect your TV to some commercial grade electronics (like a DVD player, or a game console) via the same input and the same cable you use for Arvid (and the same power socket). If the screen will look much better and without interferences, then the issue is most likely Arvid or your circuit.

Related to transceivers: I've already tried that solution - actually that was the first solution to overcome the BBB boot issue (or a feature ?). That resulted in brighness differences between the top and bottom part of the screen. It looked to me that when BBB has higer CPU load it affects the voltage values on GPIO pins (let's say instead of 3.3V it was 3V on GPIO pins - just an example). That's not an issue for digital electronics, but it is visible on analog part (made out of voltage dividers) and the TV screen. I don't want to discourage you, feel free to experiment, maybe some voltage regulator should fix it. But such solution was against my original goal - to be a very simple circuit. Ideally the whole circuit would be just resistors, but the design/placement of the GPIO pins on BBB, and the boot indicators was IMO very unfortunate, therefore I had to add the only Arvid's IC in.

I'll make a video over the weekend, so you have a comparison how the picture is suppose to look like on RGB CRT TV.

ole00 commented 4 years ago

There's some older pictures of Arvid's CRT TV output: http://www.molej.cz/files/arvid_tv_test1.jpg http://www.molej.cz/files/arvid_tv_test2.jpg http://www.molej.cz/files/arvid_tv_test3.jpg

Even though test3 shows visible moire pattern, I'm pretty sure that's how the camera interprets it. No moire wen looking in person.

asimonf commented 4 years ago

The video I uploaded was mostly to show the interference coming out of my circuit. It shows as red interference in a black background. The wobble isn't that noticeable on camera.

I'm starting to believe that my TV is part of the problem. I can see a sort of "S" like interference on the TV without any input connected. I plugged a component cable and touched one of the chroma inputs to make it more visible, but without the cable you can see a faint dark swirl:

IMG_20200429_181925

I think that interference could be affecting horizontal timings, which would show as a slight wobble.

I tried changing plugs but I live in a building. It's entirely possible something is contaminating my TV's power. Although it's also possible my TV is just aging. I tried unplugging possible sources of interference but it doesn't seem to change.

I'm also sure my circuit is part of the problem too, because with your circuit I don't see brightness flickering on the color band patterns.

I bought a ferrite core to attach to the power cable to see if that helps (a few cents, but I have to wait for it to arrive).

With regards to the buffer, I took the idea from a schematic I saw of the Amiga A600. It's graphics chip outputs color in 4-bits per channel. It uses an octal buffer to buffer the sync signal and the color signals as they go out of the video chip. The color signals then go to a binary weighted resistor DAC much like the one in Arvid and then uses a 2n3904 transistor to buffer the DAC output and into the video encoder (interestingly, it doesn't use an opamp).

The Amiga schematics have been a source of inspiration because I've been studying their schematics for an unrelated project (I want to build a cheapish console using old parts similar to what you'd find in an Amiga PC), but I must admit I can't understand the layout in certain cases, nor the choice of components. I still haven't fully grasped the A600 DAC part.

ole00 commented 4 years ago

I've made a video of picture stability here. It shows how the TV signal looks like in my conditions / environment.

asimonf commented 4 years ago

Thanks for that. I modded my TV to accept RGB input to make it easier to test. I'll compare it this weekend. The more I look at it, the more it seems like it is interference on my TV, but I still lack the equipment to test that out.