Open stevenhoefel opened 2 months ago
Hi,
For the 800x200 monochrome mode I would change the MDA_720x350@50 entry in TimingsVGA.h (at least for now). Make sure the F
, Vis
and B
fields are multiples of 4, otherwise the Pico will freeze.
From the figure you posted above, I guess the pixel clock is 15MHz, and H sync polarity is positive and V sync polarity is negative.
Something like this may be a good start, though I have not adjusted the porch sizes (please do so if needed and remember they should be multiples of 4, though I don't think they are super critical):
{16, 800+XB, 20, 126, 20, 200, 4, 16, Pos, Neg, 15798, 50, 15000000, 1},
I think that updating this line shouldn't cause the Pico to freeze and should display something.
Oh btw, don't change the DisplayBuffer's Buffer
dimensions, 800 monochrome should fit fine, as we are storing 2 pixels per byte horizontally. If you increase the size, the Pico will run out of memory and will freeze.
Debugging is tricky but can be done via USB. You can use -DDBGPRINT=on
in cmake which turns on some basic debugging. If you have configured the TimingsVGA.h
correctly then you should be seeing messages like "Updating Buff.Mode=" that match your modified MDA mode.
Otherwise you may be seeing messages like "Could not match Polarity"
The issue is that printing things via USB can mess up with the timings and you get a noisy image on the VGA, but works all right as long as you don't print too often. I usually print stuff in TTLReader.cpp in runForEver()
, see commented out lines towards the bottom.
After you get it to show things, you may need some vertical pixel doubling, like in 640x200 EGA mode, similarly to how it's done in VGAWriter.cpp: DrawLineVSyncHigh4x1(Line/2)
instead of Line
.
I hope this helps, feel free to reach out again if you run into issues.
After a lot of tinkering, the best I could produce was a pretty-good image hanging off the top-left of the screen. I'm going to guess it off by around 10 columns, both vertically and horizontally.
It wouldn't work by amending the MDA line... instead I had to amend the EGA 640x200 which makes me think there's other calculations going on for MDA that don't apply to EGA. The line that produced an image was:
/EGA_640x200@60:/ {36, 720+XB, 20, 56, 32, 200, 56, 16, Pos, Pos, 15798, 72, 15798000, 1},
Note the 72hz for the Vertical Frequency and Positive V Sync. Otherwise the code reported no matching configuration. From here, should I just adjust the borders/offers to center this EGA picture? Or should I work harder to get the MDA method to match?
I'll tinker more again tomorrow and review how the code paths for MDA and EGA differ...
Just a note on the wiring, video is wired into all three TTL_PG, TTL_PR and TTL_PB on the input side of the 74LVC245. Ground from the video port is tied into TTL_SR, TTL_SB amd TTL_SG. H and V sync are wired into their counterparts.
Attempting to use the modeline configuration row above in the MDA_720x350 Timings 'slot' just causes a clear black screen with no image data present at all.
Ah nice, you got some image :D
Well the buffer for EGA/CGA is only 640 pixels wide, so it won't fit 800 pixels unless you make the buffer wider but shorter, but in that case you won't be able to switch to EGA/CGA. This is why I would try to modify the MDA mode instead of using EGA/CGA. Also you would have to wire it carefully to get the intensity working.
Hmm are you using the project's wiring? If not, then this is probably why MDA is not working. MDA is using different GPIOs. It's using GP6 to GP9 for V, H, INT, PB (see the schematic), while CGA/EGA is using GP0 to GP7.
I've soldered/wired everything together on a prototype schematic, wiring all same-named pins between the 74LVC245 and the Pico together. I had initially assumed that my monitor would need its 'video' wired into all R/G/B to get a white colour. This would also cause the right signals through to GP6 - 9. So I had wired it as follows:
I can see how this makes the unit think that an EGA signal is coming in as there's data on all. Tongiht I'll reduce that wiring and only feed video in on TTL_PB with ground for intensity and see if I can get MDA working.
Meanwhile, based on your note above, I've been checking with GP6-9, but that doesn't line up with the schematic?
Am I missing something with that pin wiring? Do you send the MDA data in on the original MDA pins?
Sorry, I was wrong. Common.h lists the GPIOs used by each mode: EGA: GP0-5: BBGGRR GP6:V GP7: H CGA: GP8-13: BBGGRR GP6:V GP7: H MDA: GP26: Intensity GP27: Video
After a lot of tinkering, I have a horizontally-centered vertically-squished picture! I had to lower the pixel clock quite a bit to get the full set of pixels for each row to display. I also had to lower the count to 720 pixel visibles? I must admit there is too much guesswork involved on my side.
The currently-configured row for MDA is:
/MDA_720x350@50:/ {16, 720+XB, 20, 126, 20, 200, 4, 16, Pos, Pos, 15798, 72, 13018181, 1},
I also had to set the XBorderInit to 0 to get the picture off the edge of the screen. I'll review the pixel doubling, as mentioned, in the EGA section and see how this all goes.
The Apricot also loves to send out spurious H Sync signals on power-up and power-down, causing the Pico to lock quite often. I'll have to work out where the calc overflows are happening. Just bounds-checking the return of getHZ in DisplayBuffer.h wasn't enough.
Pixel doubling is easy, you just need to use Line/2
just like in VGAWriter.cpp:230
This is strange. Lower pixel clock should make the image wider.
But with a lower pixel clock you would indeed need a shorter H_Visible, otherwise readLineMDA
would be waiting for more pixels to arrive and would loose synchronization with the PIO that provides the data (see if (PixelX > XMaxPixelX) { break; }
).
The way it works is that TTL is read by Pio/MDA720x350_*.pio
. This reads the pixels at the specified pixel clock and pushes them into the queue for readLineMDA()
to received them on the host side (uint32_t MDA8 = pio_sm_get_blocking(...)
). The pio will break out of the data loop if it detects a positive HSync, and wait there pushing zero values until the new line. In the meantime the host is counting pixels with the BuffX
counter and checks against Timing[MDA_720x350_50Hz][H_Visible]
, and will break out of the loop if it thinks that it has received the whole line. So both H_Visible and the pixel clock of the Pio must be fairly close to the correct value, otherwise you can get weird race conditions.
Btw you have overclocked the Pico haven't you? I would only get a stable image with cmake -DPICO_FREQ=270000
.
Apologies for the delayed response as there's been a lot of tinkering on this side to get the image displayed. Indeed the Pico is overclocked to 270000 as per the make command in your CMakeLists.txt.
Going back to the specs in the first image in this post, I attempted to get the full 800x400 (80x25 chars at 10x16 per char) displayed which meant a vertical resolution of 400 pixels. Of course, as you mentioned, this wouldn't fit in the Pico RAM with the 640px width, so I shrunk the Buff array to 400x400 as we're storing 2px per byte.
This worked, but then it became apparent that I'm reading two input lines at once and overlapping them? Doing the "Line / 2" in VGAWriter stretched this out, but that can't be the right answer as I assume the image (once I have an input device and can display a full proper image that covers 100% of the display) will only show half.
With the doubled line, you can see that sometimes the pixels are showing the "odd" line, and sometimes the "even" line, creating a pretty jittered image. So. Another problem for next week when I'm back near technology!
I really feel like double-pixel is the right height, just not the right density. I should be reading 400 lines and displaying 1:1, instead of reading 200 lines and doubling.
I'm currently waiting on parts for the keyboard interface, so I'll update when I tinker more!
The image looks very fuzzy, which could mean that the pixel clock is not correct.
I doubt that pixel doubling is the issue, it should produce pixel-perfect output. The only distortion you should be getting is from the LCD monitor's scaler.
The Apricot XI PC provides an MDA-like display with 800x400 pixels at 15.798khz H and 71.9 V. I've managed to compile and build the project. I then attempted to manipulate the existing MDA mode to these settings, but I can't stop the Pico from freezing up. I also don't have a proper debugging setup and using USB serial isn't a good method.
Any chance you could provide some guidance on how to add this archaic display mode?
Thank you!