This is an amazing project! I am glad people like the PS2 even after so many years and the projects around it get more and more interesting!
I have been doing small software and hardware projects on the PS2 as a hobby, but completing them is commonly difficult.
Thanks! The PS2 was my first console, so I will also always have a soft spot for it! I've been modding mine already as a kid 20 years ago, so it's really fun to do something more serious with it now
Also thanks for the infos regarding the CS, it's quite hard to find information like that online! I haven't seen /CSPPC yet, could it be that it's one of the pins 12, 13 or 14 on the bios chip? Anyway, handling the CS on the bios flash is quite flexible, we found a couple of ways already that seem to work. Only for getting the DVD ROM to function it's a bit more complicated so far, as it requires 16 bit data by default. In a portbale it's not needed anyway as there is no disk drive, but I could imagine physical games wouldn't work without it(?)
While I'm typing already, I forgot to write an update again....
Video Output
Soooo... on the FPGA side I have found and fixed the issues from the last update.
The noise in the image was actually just a timing issue when driving the screen, as seen in my last edit.
The artifacts and lag every now and then were caused by frame drops in GTA. This is something I didn't think about initially, but now it makes sense. For PAL, the video output is fixed at 50Hz - independent of the ingame framerate. For a 25fps game this means that a frame consisting of 2 fields is output at 25Hz.
Now to the issue: When the game framerate drops below 25fps and the video output is fixed at 25Hz, some fields/frames will need to be sent twice to keep the output stable (most likely applicable to FMV scenes too).
In my first deinterlacer implementation, my assumption was that a frame always starts when HSYNC is low directly after a rising edge of VSYNC. My algorithm would then stitch the following 2 fields together and display them. I think usually this assumption would be correct, but in the case of lag spikes, this cannot be guaranteed. In the worst case, the deinterlacer would then combine fields from 2 completely different frames, which causes the combing artifacts and the additional lag.
My first fix for this was to always stich 2 subsequent fields together, which also doubles the output framerate from 25Hz to 50Hz. It works OK for games that run at 50fps, but for <25fps games it always generates combing artifacts, because in 50% of the time 2 different frames are combined.
The next implementation was just a simple line double and that was the point where I discovered all this. The line double had no issues at all, because it was displaying 1:1 the input, just line doubled. It looks horrible, though....
A couple of iterations of various algorithms later I started feeling the need for a motion adaptive deinterlacer, as it would fix most of my issues with the weave deinterlacer and the quality issues of the line doubler. This is exactly what I did and here is a demonstration of my motion adaptive deinterlacer algorithm:
It's a hybrid between a 2-field and 3-field motion adaptive deinterlacer. Ideally it would have been a 5-field algorithm, but I don't have the memory bandwith to pull that off.
The performance is still pretty good, the 3-field part handles most of the motion detection and in the cases where it misses some motion (fast moving objects, mainly in 50fps games), the 2-field part kicks in and detects motion. When motion is detected, I'm doing a simple interpolation between the pixels above and below. When no motion is detected, weave deinterlacing is performed.
Another thing to mention is that the algorithm calculates every missing pixel of a field individually, compared to some implementations that group a bunch of pixels together.
The "calibration" is based on two thresholds, one that sets the allowed motion value and one that inhibits the noisy nature of the 2-field motion detector. I adjusted both to make the result look good in most situations, but it still needs some tweaking.
In some parts of the video I modified the calculations to display movement detected by the 3-field part in pink and the output of the 2-field detector yellow. It performs exceptionally well with 50fps games, apart from some minor combing present on very fast moving objects & some noise caused by false detections. In GTA SA (~25fps) it looks great too, but there (last quarter of the video) you can start to see the main weakness of the algorithm: during lag spikes, when a field is displayed multiple times, the motion detector cannot detect any motion, which leads to the flickering you see in some scenes. It's really only noticable when the interpolated pixels are colored pink, but it still bugs me a little bit. Proper motion adaptive deinterlacers have some sort of "decay" function that stores the motion values for each frame and gradually adjusts them according to the current motion value.
Mine doesn't do that right now, but I was thinking about how to best implement it & it might be possible to do it by rewriting parts of the framebuffer scheduler...
I also got two new displays from
here and tested them; the display in the video is actually a new one. Overall they look OK - viewing angles are perfect, colors are ok, brightness is good - and they have somewhat decent datasheets. What really bothers me though, is the dithering they do. When first turning them on, the flickering caused by it is very distracting, but it seems to disappear when the displays are on for a while. Still not comparable to the outstanding image quality I got with the old waveshare display, but much better than some other displays I've used in the past.
There still a shitload of work ahead for the video processor:
- look into implementing a "decay" for the motion values
- write a (bilinear?) scaler (especially needed for PAL)
- implement support for 480p and 480i
- Everything I wrote so far should be natively compatible with NTSC, but I have no way right now to measure all the parameters I need to know in order to make the input state machine lock onto the video stream. For 480p I will need to change the fsm of the deinterlacer to just pass the data through for progressive video
- the input state machine will need some refactoring, as the new screens are a bit picky when it comes to video dropout during boot or while launching a game. I will need to reset the video processor and the display when the fsm loses synchronisation to the input signal
- I will still need a module that enables me to draw sprites onto the screen via the syscon (e.g. battery level)
I think with the motion adaptive deinterlacer it's looking pretty good already - that one caused a lot of sleepless nights...The next headache will for sure be the scaler...
Next topic:
To not lose momentum regarding the electrical/mechanical design, I started to work on the new mainboard revision with slightly reduced priority. I already copied the circuits from all my extension boards into the schematics (which was a big pain in the ass - libraries) and started working on a first housing concept to define the board outline and component placement. I would say the schematics are about 80% done and I'm sitting at exactly 30 pages right now. Cross checking this one will definitely take some time and I'm fully expecting this to not work first time, so I will be adding a lot of debugging/troubleshooting features to be sure. The mainboard will be about the size of a 5 inch LCD, most likely a bit bigger for mounting purposes.
Usually I don't share very preliminary stuff, but here is a very early concept for the mainboard, nothing is routed, the connectors are placeholders, and it will most likely still change a lot:
I have a rough drawing of the housing front view, but sadly I cannot share it as solidworks refuses to launch since the last (forced) update on monday.
In short, this is the idea:
- 3 or 4 piece construction; the mainboard, display, gamepad and batteries will be mounted in their own subassembly, call it "skeleton", which is sandwiched between the top and bottom housing. This allows for easy debugging, assembly and shell swaps.
- The holes around the edges of the first mainboard concept are meant to have 2 purposes:
- mount the mainboard to the display subassembly
- securely attach and ground the heatspreader/shield I was experimenting with in one of my previous posts
- The SD card slots will probably be on their own rigid/flex PCB, which attaches to the expansion connector in the top left
- 2 18650 or 21700 cells; replaceable. The housing will probably have a cell on each side in the grips, which would make the grips ~30mm thick; the center would then be about ~16mm thick
- 18560 vs. 21700: I did a quick runtime test to see which battery would satisfy my 3h runtime requirement. The test was done with 2 2500mAh 18650 cells from my junk pile (they are from ~2013, left fully discharged for a while) and I managed to reach about 2.5h in GTA SA at full display brighness. This makes me believe that 2 3500mAh 18650s would be sufficient, in case I cannot fit 21700 cells
- For the buttons I'm planning to use PSVita buttons. I actually ordered and received some for testing. I'm considering these tact switches for the dpad and action buttons, after trying all variants I concluded that I prefer the 100gf variant. Start, select and power will most likely use something like this. The shoulder buttons and triggers are not decided yet
- The analog sticks will for sure be hall effect switch sticks, probably in the XBOX arrangement. I got myself these and I quite like the look and feel compared to the Gulikit sticks
- For cooling I'm planning to use a switch lite fan, controlled via PWM
Overall the progress slowed down a little due to the video processor implementation, but I'm having a lot of fun doing it
It's good though to do some electrical/mechanical design again, I already started writing "if() then" accidentally in my C code recently....too much VHDL