What's new

Worklog Some PS2 Project

Joined
Sep 27, 2016
Messages
469
Likes
1,050
Thanks for the suggestion! I reached out to them, but unfortunately they were not able to assist with a custom screen lens :(
I was told that they are not offering this as a service, so I think a custom glass screen lens is finally off the tabe.

I also received the custom tempered glass screen protectors I requested from a local shop and those were a flop too. The glass layer was only about 1/3 of the overall thickness and it was not possible to peel the 2/3 of plastic off without shattering the glass.

The option of manufacturing a screen lens myself from 1mm PC sheets actually worked quite well. For that I designed myself a little jig to cut the shape with a scalpel and another fixture to paint the bezel on the backside. The paint I used was a can of Tamiya PS-5. This would indeed be a feasible option, but the lens scratches very easily - After a week of daily driving the portable during my commutes, the lens was all scratched. (bumping the thing around in my backpack certainly didn't help...)

While I was experimenting with the PC lenses my package from aliexpress arrived...
All 3DS XL screen lenses were nicely packaged and look quite good. Overall size is about 113.2x70.7mm, the window is about 107.2x64.4mm and the tickness is exactly 1mm. The corners are asymmetric, 2 corners have a ~3.5mm radius and the other 2 have a ~1.5mm radius. The adhesive is as cheap as the price suggests, but it can be peeled off very easily to use other methods of attaching the lens to the housing.
I continued by printing an adjusted version of the front housing to give it a try - and while I wasn't a fan of the thin bezels in the beginning, I think I got used to them now:

View attachment 36646
This will be the one, I think. The window perfectly fits the visible display area vertically, horizontally it's just a little bit too narrow (by ~1mm). It's not a issue when playing games at 4:3 aspect ratio, and once I have the scaler running I can take this into account too. The adhesive didn't stick to the PLA shell (possibly due to the layer lines), so for now I attached it using 2K epoxy. I'm really happy with how it turned out!

The next important tasks would be working on the FPGA and creating another revision of the gamepad flex, to fix the protruding power button (seriously, the portable turned on twice in my backpack this week). I expect work and life to be a little bit tough in the upcoming months, so progress could potentially slow down a little bit. But I hope I can manage to get some productive hours during the christmas holidays.
Awesome! Glad the 3DS XL glass lenses worked out. I noticed it slightly cuts off the image a little when I was testing them as well, but it is not too bad to where I couldn't tolerate it and sounds like you came to the same conclusion.
 
Joined
Apr 6, 2020
Messages
118
Likes
325
Me and another member were looking into driving the 24 bit RGB signal directly as well and I have some measurements that might help. Here is the HS, VS, and pixel clock measurements. I accidentally named HS HV, but just know it's HS haha. These files can be opened using Saleae logic analyzing software. This was measured on a 90001 PS2 on the home screen. Hope this helps!
Are these measurements made on the PS2 NTSC or the PS2 PAL?
 
Joined
Dec 25, 2022
Messages
51
Likes
482
Location
Landeck, Austria
Update time!

As hinted in the last update, I’ve been busy with another project, which will be finished in about a month. Luckily that did not stop me from spending some spare time on the PS2!

Travel case and SD2PSX
I’ve been using the prototype almost daily for 2h during my commutes, probably for more than a month now. It’s great! The battery life is about 4.5h at full brightness and headphones, which is a lot more than I originally intended to implement. I did notice some bugs in the firmware that need fixing in the future (like the gamepad not working after turning the system off and on a couple of times while charging).

To give the portable a bit of protection I designed a little travel case:

IMG_20250215_225717627.jpg
IMG_20250215_225742549.jpg

(The color is on purpose, so I find the damn thing again)

The original 8MB memory card turned out to be a bit of a bottleneck – I only have one and it’s full already, after finishing about 6 games! But there is hope… luckily, the PS2 scene is innovating at a crazy rate nowadays - I was made aware of the SD2PSX(td) project, which might solve all my storage issues.

I ordered a PSxMemCard Gen2 for testing and it does indeed work great! While the OPL MMCE beta 2 had some game compatibility issues similar to the MX4SIO (actually the same games didn’t work), the load times were a noticably faster and there was slightly less stutter than MX4SIO.

From experience, neutrino offers better compatibility on MX4SIO, so naturally I wanted to try it with MMCE. The only MMCE compatible launcher I could find was NHDDL (apart from XEB+ neutrino launcher). After installing the NHDDL MMCE beta 3 and neutrino 1.5.0 on the SD2PSX boot card, I was impressed to see it working as well as the previous MX4SIO setup I had. All games I tried were running fine and there is finally all the memory card space I ever need on a single device! This might be my new setup of choice!

Just the test setup is very sketchy:

IMG_20250215_230218289.jpg


To make this a bit more usable, I was looking for ways to integrate it into my portable. I decided against integrating it internally on the memcard flex early on, as I would like to keep both memory card slots fully functional. With all the advancements recently, who knows what comes next and whether it's compatible to the SD2PSX. If the 2 SD memory card slots will stay, it means that the SD2PSX will need to shrink to the size of an SD card. This enables the use of a SD2PSX, while keeping compatibility to MX4SIO and my SD memory card.

Thankfully the SD2PSX hardware only consists of an RP2040, SPI flash, PSRAM and micro-SD slot, after removing the display and buttons. In the beginning I thought this would be an easy fit, but in the end it was tight with all the signals needing accessible test points at the back. I also had to use smaller packages for the flash and PSRAM to make everything fit & select the smallest micro-SD slot I could find -> this one has no latching mechanism, which would take a lot of space.

This is the current state:

Screenshot 2025-02-15 230007.png
Screenshot 2025-02-15 230025.png


Both the flex PCB and the components were ordered. You see there are no buttons and no display – they are actually not needed for general use. My only concern right now would be the missing I2C display preventing the firmware from functioning (I really don’t want to modify the firmware, but I will if I have to). The whole PCBA will be adhered to a 3D printed frame to create an SD assembly similar to my SD memory card.

Next topic: FPGA
I was refactoring a lot of the video processor implementation and creating a top level block diagram to better plan the integration with the syscon. To get back into the topic, I wanted to replace the hybrid motion adaptive deinterlacer with a proper 4 field motion adaptive deinterlacer.

Screenshot 2025-02-15 225911.png


This however was not trivial, a 4 field motion detector requires 33% more framebuffer bandwidth compared to my previous hybrid implementation. In order to achieve such an increase I had to completely rewrite the framebuffer scheduler, video decoder module and the deinterlacer. There were 2 distinct enhancements to the architecture:
  • The video input module is no longer sampling the black borders horizontally (they are now added back by the scaler module when in 4:3 mode) – 33% improvement
  • The 3-byte pixel data is now packed into the 4-byte wide SDRAM data bus and gets unpacked by a ringbuffer in the deinterlacer module (before the upper byte of the SDRAM data was unused) – 25-30% improvement
Another issue was the SDRAM itself. Reading and writing from very different addresses in the same bank has a huge hit on bandwidth, because each time an address row must be opened and closed.
The hybrid deinterlacer had no issues, it needs 3 banks to read and 1 bank to write, and the SDRAM has 4 physical banks in total. For the 4 field deinterlacer I need 4 banks to read and 1 bank to write -> 5 banks in total. Luckily, each bank has enough space to fit 2 frames, so I decided to split each bank to create 8 “virtual” banks with the bandwidth limitation above.
In order to reduce the bandwidth impact, I changed how the scheduler handles reads and writes: The scheduler now tries to avoid switching between read and write as much as possible, often reading a full line before it schedules a write to the SDRAM. Before it was alternating between read and write after every burst, which would have resulted in a disastrous bandwidth reduction using the new banking scheme.

These enhancements to the data path made it possible to finally implement a 4 field motion detector! And it works!

The old motion implementation had its weaknesses in 50/60Hz games, due to the reliance on the error-prone 2 field motion detector. This is exactly where the new 4 field deinterlacer shines, the combing artefacts are almost completely gone in 60Hz games compared to before. With some tweaking of the motion thresholds, it could still be improved further. The performance in 25/30Hz games is about the same. The video delay of one field (16-20ms) from GS output to displayed image is also the same.
Flickering on very fine horizontal details (the horizontal lines in OPL are a prominent example) is completely eliminated in the new implementation. This was caused by the vertical averaging performed in the 2 field motion detector, leading erroneous motion detection.

After doing the new deinterlacer I started researching for the scaler, writing down the required calculations and thinking about the state machine. This is the point where I am right now, I should also focus on thinking about how to best implement the hardware sprite module and in general the interface to the syscon.

Boot rom flex
I had another boot rom reverse engineering session and using the information @wisi provided, together with my notes from previous sessions I finally figured out how to properly decode the CS lines. This enabled me to design a tiny boot rom replacement in the size of the original chip:

Screenshot 2025-02-15 230534.png
IMG_20250208_134141381_HDR.jpg


The original flash indeed has 3 CS lines – /CS1, /CS2 and /PPCS.
CS2 and PPCS access the same data while CS1 accesses the DVD rom. Using 2 AND gates it’s possible to generate one CS for the new flash. Of course, pre-deckard PS2s are missing the PPCS, so in order to make those compatible I added a pullup to PPCS (in the service manuals I saw that this pin seems to be either connected to VCC or floating). A22 also doesn’t seem to be connected on all PS2 models, so I’m basing it on CS1.
This new 64M chip has the DVD rom in the lower half and the boot rom in the upper half of the flash – it required a python script to combine them in the right order.

Soldering the BGA flash to the flex PCB is a bit tricky, as there is no stiffener which would prevent it from warping during reflow - I had to tape all 4 sides to the tray of the reflow oven. If it wasn't so expensive, I would have ordered the first PCBs already with 0.1mm stainless steel stiffener. Tape works too I guess :D

So far, I only installed one in a 90k and it performs 1:1 as the original bios chip. Due to it containing the DVD rom, even DVD movies work now!

More testing is needed to figure out the compatibility to other models. Let’s see what else comes up in the future!
 
Joined
Apr 12, 2017
Messages
225
Likes
155
Location
Canada
You sir, have single handedly advanced PS2 modding by centuries... And the fact that this is what you consider a fun little side project... One begins to wonder just what you would consider a legitimate challenge!

Since you keep saying that your current design is just a prototype, can we assume you'll be using nothing more than the little BGA chip for the Boot ROM in the next version? Either way that little flex you have it mounted on looks completely professional, and very impressive.

Also, do you really ride a train for 2 hours each day? That sounds rough. Has anyone asked about your absolutely one-of-a-kind handheld?
 
Joined
Dec 25, 2022
Messages
51
Likes
482
Location
Landeck, Austria
You sir, have single handedly advanced PS2 modding by centuries... And the fact that this is what you consider a fun little side project... One begins to wonder just what you would consider a legitimate challenge!

Since you keep saying that your current design is just a prototype, can we assume you'll be using nothing more than the little BGA chip for the Boot ROM in the next version? Either way that little flex you have it mounted on looks completely professional, and very impressive.

Also, do you really ride a train for 2 hours each day? That sounds rough. Has anyone asked about your absolutely one-of-a-kind handheld?
Hey, thanks I guess!

I know it’s a bit weird to call it a prototype, as it’s perfectly usable like this. It mainly serves as a daily reminder for myself to correct all the little details that bother me on the hardware side & to finish the software side so it complies with the requirements I defined :D

Regarding the BGA boot rom, that’s just a small side project at this point. Right now, it doesn’t have many use cases (apart from maybe 70k and 90k consoles), but who knows what the future brings! For the final mainboard revision I will probably stick to the TSOP48 flash, having a BGA chip on the underside would make soldering unnecessarily difficult and having the whole boot rom flex would be another addition to the BOM cost. (even exluding the expensive BGA adapter for the TL866)
With this flex PCB the main goal was to test the new circuit around the flash, as I would like to reuse that on the mainboard for future proofing (in case someone finds out how to launch homebrew from the dvd rom). But apart from that, I do have some more boot rom things going on in the background!

The commutes were actually a big motivation for starting this project to begin with. It’s 3h in total per weekday, but two of them can be made useful at least. I tried pretty much everything to have some productive time, but the only thing that kind of worked was some light programming… and even that led to lots of bugs, it’s just hard to focus in the train.
-> Perfect application for a portable! I used to bring the steam deck, but now it mostly got replaced by the PS2. Actually, unlike the steam deck, nobody ever commented on it. In the end my design goal was to make an inconspicuous black box with a screen, which means that goal was successfully achieved already!
 
Joined
Mar 17, 2016
Messages
88
Likes
58
With this flex PCB the main goal was to test the new circuit around the flash, as I would like to reuse that on the mainboard for future proofing (in case someone finds out how to launch homebrew from the dvd rom).
Isn't FreeDVDBoot a thing already? Or do you mean something different?
 
Joined
Dec 25, 2022
Messages
51
Likes
482
Location
Landeck, Austria
Isn't FreeDVDBoot a thing already? Or do you mean something different?
By that I mean replacing the DVD player with homebrew in the DVD rom itself, essentially making full use of the reprogrammable ROM. The DVD player would just be wasting memory space in a portable, so why not use the 4MBytes of flash for something else? Right now it seems to have more limitations than benefits, but as it's already possible to store applications in the boot rom, it might be possible to make use of those 4MBytes one day.
 
Joined
Mar 17, 2016
Messages
88
Likes
58
By that I mean replacing the DVD player with homebrew in the DVD rom itself, essentially making full use of the reprogrammable ROM. The DVD player would just be wasting memory space in a portable, so why not use the 4MBytes of flash for something else? Right now it seems to have more limitations than benefits, but as it's already possible to store applications in the boot rom, it might be possible to make use of those 4MBytes one day.
Ahh, that makes more sense, thanks
 
Joined
Mar 12, 2023
Messages
2
Likes
0
By that I mean replacing the DVD player with homebrew in the DVD rom itself, essentially making full use of the reprogrammable ROM. The DVD player would just be wasting memory space in a portable, so why not use the 4MBytes of flash for something else? Right now it seems to have more limitations than benefits, but as it's already possible to store applications in the boot rom, it might be possible to make use of those 4MBytes one day.
if you’re able to modify the boot rom, does that mean you can add USB 2.0 to the PS2?
 

Y2K

"The PS1 Guy"
Staff member
.
.
.
Joined
Apr 14, 2022
Messages
206
Likes
459
Location
Chicago, IL
if you’re able to modify the boot rom, does that mean you can add USB 2.0 to the PS2?
Not how that works, unfortunately. The USB 2.0 spec requires an updated hardware PHY that can handle low-speed -> full-speed -> high-speed negotiation, which the USB 1.1 PHY in the PS2 would only be able to set up full-speed at most - this is a hardware limitation, not a software one.
 
Joined
Mar 12, 2023
Messages
2
Likes
0
Not how that works, unfortunately. The USB 2.0 spec requires an updated hardware PHY that can handle low-speed -> full-speed -> high-speed negotiation, which the USB 1.1 PHY in the PS2 would only be able to set up full-speed at most - this is a hardware limitation, not a software one.
You would still need the USB2.0 drivers which are in the rom IIRC.
Edit I am pretty sure I’m wrong here.

Couldn’t you update the microcontroller?
 
Last edited:

Y2K

"The PS1 Guy"
Staff member
.
.
.
Joined
Apr 14, 2022
Messages
206
Likes
459
Location
Chicago, IL
You would still need the USB2.0 drivers which are in the rom IIRC.

Couldn’t you add the physical hardware and modify the rom to use USB2.0, at least in theory?
No, the USB PHY is baked into the die on the CXD2976GB (combination Emotion Engine & Graphics Synthesizer) and cannot be removed or be replaced by something else.
 
Joined
Apr 6, 2020
Messages
118
Likes
325
You would still need the USB2.0 drivers which are in the rom IIRC.
Edit I am pretty sure I’m wrong here.

Couldn’t you update the microcontroller?
The way the IC was built, the circuits inside it made in silicon cannot be changed, it is a physical part of the chip, there is no code that can be changed, the IC simply cannot be changed.
 
Joined
Dec 25, 2022
Messages
51
Likes
482
Location
Landeck, Austria
Hey, time for a tiny update!
This time there are two topics to discuss:

SD2PSX
Well, I got all the parts & the flex PCBs and assembled one SD card sized SD2PSX. After I cleaned the PCB, I continued by adhering the top & bottom 3D printed parts to the flex PCB using 2K epoxy (also potted all circuitry in epoxy to avoid any solder joint failures down the road, due to mechanical stress). I then soldered a USB cable, I2C display and two buttons to the test points and flashed the latest SD2PSXtd firmware. Sadly, the first setup still required the display (setting it to PS2 mode, enabling autoboot and deploying CIV.bin), but afterwards it works just fine without the OLED screen connected. I actually don’t know why this is required, as there is a config file on the SD card with the right settings (but it seems to be ignored?).

IMG_20250308_180213923.jpg
IMG_20250308_180236730.jpg


I can also confirm that the smaller sized packages for the PSRAM and SPI flash work just fine (no surprise), here are the part numbers for reference: W25Q128JVPIQ (flash) and APS6404L-3SQR-ZR (PSRAM). Without those, it wouldn't be possible to make the circuit this small.

I’ve installed NHDDL on the boot memory card and also transferred over all my save files, from then on it “just worked”. I actually really like NHDDL, it’s really clean & simple and boots straight to the games without touching any settings! So far the gaming experience and compatibility is about equal to the MX4SIO, with the big benefit of being able to store all savegames on it. Another big plus is being able to plug it into my fat PS2 to continue playing on the TV!

What bothers me right now is a potential bug I found in my gamepad emulator. For some reason the gamepad is unresponsive when launching NFS MW from MMCE, it does work just fine when launching it from MX4SIO. I don’t have my debugger here right now, but this one definitely gets onto the list of bugs to fix.

A couple other points I noted about the hardware itself:
  • The card is currently a bit thick; it should be reduced by 0.1 to 0.2mm in the next revision (you can already see wear marks on some contacts due to it)
  • The test point position below the micro SD card is not ideal, the lack of a stiffener there makes that spot of the flex PCB really fragile -> maybe move them to somewhere under the RP2040 in the next revision.
  • The bottom 3D printed piece is necessary to avoid deformation of the micro SD slot when inserting a card. The slot is so thin and small that it relies on the PCB to keep it in shape.
  • An alignment feature on the printed parts would be ideal for reproducible assembly

FPGA & Menu
On the FPGA side I’ve been working on finally displaying the config menu on-screen. For that I had to define the interface between syscon and FPGA a bit better, develop a small FPGA SPI slave module, conceptualize and design a sprite module for the FPGA and adjust the output data path of the video processor to fit the sprite module.

This would be the current SPI interface approach:
  • CPOL = 1 & CPHA = 1 (SPI mode 3)
  • 25MHz clock speed
  • CS active high
  • 8 bits per transfer
  • Each SPI packet consists of at least 1 command byte(read/write) followed by a 2 byte register address and then at least 1 data byte
  • There is no limit on transferred data bytes per packet, the SPI slave will happily receive/transmit data without wait cycles until CS goes low
  • Reading from the FPGA is implemented in the SPI module, but currently not used/untested. I actually can't think of any use-cases right now
Essentially, the syscon treats the video processor as one big memory. Internally, the SPI slave handles the banking and distributes the data to the correct module, depending on the address. Register access is handled internally by each module.
The sprite module is currently the only module accessible by the SPI interface. The accessible part essentially consists of 3 banks: 1 bank for control registers (x/y position of sprites, text color, background color), 1 bank to store the sprites to draw on the screen (up to 512 sprites at the same time) and 1 bank that stores the font (up to 128 individual sprites, the syscon loads it at startup).

Initially I was planning to store the sprites in the framebuffer, which would have no limitation regarding number of sprites on screen, or the size of sprites. But with the 4-field deinterlacer I don’t have much bandwidth left to cover the sprites there. Additionally, it would have been a real pain in the ass to adjust the menu to resolution changes on the input side.
Now the sprite module resides between the scaler and the CDC linebuffer for the video output module, so it needs to store all sprites to display in its own buffer. That’s were the limitation of 512 sprites comes from. There is also a limitation of ~30 to 40 sprites per line currently. The sprite drawing state machine is still quite inefficient right now and I will need to improve it, that should probably boost the amount of sprites that can be displayed per line to about 60-70.

Here is a small demonstration of the current implementation:


The menu itself works quite well and even some of the settings are working already (volume, analog stick calibration, storing settings). You can also see that the main menu displays the state of charge and EE temperature, which is refreshed in 1s intervals. Something similar is done in the power management monitoring menu, you can see that it displays the power consumption, time to full and time to empty currently.
You can also see that the font size is ridiculously tiny… for some reason I was overestimating the size of 8x8 pixel sprites. I think the next step is to implement integer scaling of the sprites, it should not be difficult to do. I will probably implement it as global scaling factor, instead of allowing each sprite to be scaled individually -> much easier and as I’m mostly only displaying text, I don’t see a benefit in having different sized sprites on the same screen.

All in all this is already a huge step forward for the menu! There are so many puzzle pieces that need to work together in order to display even a single sprite…
This now also opens the door for configuring other aspects of the video processor via the syscon!
FPGA LUT utilization is now at about 25% and the whole video processor is using about 50% of the available block RAM, so we're still good in that regard.
 
Joined
Apr 6, 2020
Messages
118
Likes
325
Hey, time for a tiny update!
This time there are two topics to discuss:

SD2PSX
Well, I got all the parts & the flex PCBs and assembled one SD card sized SD2PSX. After I cleaned the PCB, I continued by adhering the top & bottom 3D printed parts to the flex PCB using 2K epoxy (also potted all circuitry in epoxy to avoid any solder joint failures down the road, due to mechanical stress). I then soldered a USB cable, I2C display and two buttons to the test points and flashed the latest SD2PSXtd firmware. Sadly, the first setup still required the display (setting it to PS2 mode, enabling autoboot and deploying CIV.bin), but afterwards it works just fine without the OLED screen connected. I actually don’t know why this is required, as there is a config file on the SD card with the right settings (but it seems to be ignored?).

View attachment 37897View attachment 37898

I can also confirm that the smaller sized packages for the PSRAM and SPI flash work just fine (no surprise), here are the part numbers for reference: W25Q128JVPIQ (flash) and APS6404L-3SQR-ZR (PSRAM). Without those, it wouldn't be possible to make the circuit this small.

I’ve installed NHDDL on the boot memory card and also transferred over all my save files, from then on it “just worked”. I actually really like NHDDL, it’s really clean & simple and boots straight to the games without touching any settings! So far the gaming experience and compatibility is about equal to the MX4SIO, with the big benefit of being able to store all savegames on it. Another big plus is being able to plug it into my fat PS2 to continue playing on the TV!

What bothers me right now is a potential bug I found in my gamepad emulator. For some reason the gamepad is unresponsive when launching NFS MW from MMCE, it does work just fine when launching it from MX4SIO. I don’t have my debugger here right now, but this one definitely gets onto the list of bugs to fix.

A couple other points I noted about the hardware itself:
  • The card is currently a bit thick; it should be reduced by 0.1 to 0.2mm in the next revision (you can already see wear marks on some contacts due to it)
  • The test point position below the micro SD card is not ideal, the lack of a stiffener there makes that spot of the flex PCB really fragile -> maybe move them to somewhere under the RP2040 in the next revision.
  • The bottom 3D printed piece is necessary to avoid deformation of the micro SD slot when inserting a card. The slot is so thin and small that it relies on the PCB to keep it in shape.
  • An alignment feature on the printed parts would be ideal for reproducible assembly

FPGA & Menu
On the FPGA side I’ve been working on finally displaying the config menu on-screen. For that I had to define the interface between syscon and FPGA a bit better, develop a small FPGA SPI slave module, conceptualize and design a sprite module for the FPGA and adjust the output data path of the video processor to fit the sprite module.

This would be the current SPI interface approach:
  • CPOL = 1 & CPHA = 1 (SPI mode 3)
  • 25MHz clock speed
  • CS active high
  • 8 bits per transfer
  • Each SPI packet consists of at least 1 command byte(read/write) followed by a 2 byte register address and then at least 1 data byte
  • There is no limit on transferred data bytes per packet, the SPI slave will happily receive/transmit data without wait cycles until CS goes low
  • Reading from the FPGA is implemented in the SPI module, but currently not used/untested. I actually can't think of any use-cases right now
Essentially, the syscon treats the video processor as one big memory. Internally, the SPI slave handles the banking and distributes the data to the correct module, depending on the address. Register access is handled internally by each module.
The sprite module is currently the only module accessible by the SPI interface. The accessible part essentially consists of 3 banks: 1 bank for control registers (x/y position of sprites, text color, background color), 1 bank to store the sprites to draw on the screen (up to 512 sprites at the same time) and 1 bank that stores the font (up to 128 individual sprites, the syscon loads it at startup).

Initially I was planning to store the sprites in the framebuffer, which would have no limitation regarding number of sprites on screen, or the size of sprites. But with the 4-field deinterlacer I don’t have much bandwidth left to cover the sprites there. Additionally, it would have been a real pain in the ass to adjust the menu to resolution changes on the input side.
Now the sprite module resides between the scaler and the CDC linebuffer for the video output module, so it needs to store all sprites to display in its own buffer. That’s were the limitation of 512 sprites comes from. There is also a limitation of ~30 to 40 sprites per line currently. The sprite drawing state machine is still quite inefficient right now and I will need to improve it, that should probably boost the amount of sprites that can be displayed per line to about 60-70.

Here is a small demonstration of the current implementation:


The menu itself works quite well and even some of the settings are working already (volume, analog stick calibration, storing settings). You can also see that the main menu displays the state of charge and EE temperature, which is refreshed in 1s intervals. Something similar is done in the power management monitoring menu, you can see that it displays the power consumption, time to full and time to empty currently.
You can also see that the font size is ridiculously tiny… for some reason I was overestimating the size of 8x8 pixel sprites. I think the next step is to implement integer scaling of the sprites, it should not be difficult to do. I will probably implement it as global scaling factor, instead of allowing each sprite to be scaled individually -> much easier and as I’m mostly only displaying text, I don’t see a benefit in having different sized sprites on the same screen.

All in all this is already a huge step forward for the menu! There are so many puzzle pieces that need to work together in order to display even a single sprite…
This now also opens the door for configuring other aspects of the video processor via the syscon!
FPGA LUT utilization is now at about 25% and the whole video processor is using about 50% of the available block RAM, so we're still good in that regard.
It's incredible how you're taking this project to another level. And to think that there's still a lot to be done on the PlayStation 2. We continue to share the projects so that others can be inspired and create innovations for the portable console scene. Congratulations, my friend, excellent work.
 
Joined
Dec 25, 2022
Messages
51
Likes
482
Location
Landeck, Austria
Finally, it’s time for an update!

Since the last update I was mainly busy with the FPGA and firmware, so here are a couple of points:

Menu
Last time I complained about the text size of the menu. To fix it, I enhanced the sprite module to include a global integer scaling factor. The sprite module will essentially scale all sprites on the screen by that factor and I made sure to include it in a register to access it from the syscon via SPI.
I’m not intending for this to be modifiable; it will be hardcoded. In the video below you can see a scaling factor of 2, which makes each sprite 16x16 pixels -> This would be my preferred text size and I will most likely keep it.

Configuration of the Video Processor
Implementing the sprite module and SPI controller in the FPGA were the testing ground for adding a feature I’ve been working towards a lot in recent months: controlling various aspects of the video processor in real time via the syscon’s configuration menu. My goal was not only to add debug related settings, but also allow changing the input and output resolution, the horizontal phase, motion threshold and more.

Although it could be implemented in the syscon, right now my plan is not to have any configuration profiles – each resolution (512i, 480i and 480p) has its own independent set of configuration registers. The video processor then applies the correct settings when the respective resolution is detected. There are 3 additional registers:
  • Resolution: read only; reports the currently detected video resolution
  • Video Enable: write only; puts the whole video pipeline into reset when enabled
  • Lock Config: write only; when enabled the video processor will store, but not apply any new configs transferred via SPI. Safety feature to prevent possible race conditions when transmitting multi-byte settings.
At startup the syscon must first load all settings and then write to the video enable register to start the video processor. Changing the settings is also handled via the syscon and can be done at any time. The procedure is as follows:
  • Read the current input resolution from the video processor to apply the correct setting
  • Lock the configuration registers.
  • Update the desired settings for the respective resolution
  • Unlock the configuration registers to apply the new settings
Luckily, I was defining the architecture with this in mind from the beginning, so all I needed to do for the most part was updating the video input module and adding a module containing all configuration registers accessible via SPI. The video input now has an additional state at the start of each frame to load the respective settings from the configuration registers instead of hardcoded constants. Those are pushed through the video input CDC buffer and distributed to all modules needing them. All modules sample the video config at the start of each frame as first step in their state machine, which made the implementation much easier. This makes the design quite robust in regards to modifying these settings in real time.

LCD Backlight PWM
This module was also finally implemented and is now accessible by the syscon. Its functionality is actually quite similar to the PWM peripherals in the RP2040 - it contains 2 registers: max_count and trigger_count. It's just a counter fed by the 150MHz global clock and it counts to max_count before it resets both the counter and PWM signal. When it reaches the value of trigger_count it toggles the PWM output signal. That's it. max_count is hardcoded in the syscon to achieve about 46kHz PWM frequency and trigger_count is used to control the brightness.

Bilinear Scaler
This is the last “big” module needed to fulfill my initial requirements. Even though a bilinear scaler is quite a simple scaling algorithm on its own, I was expecting this one to be challenging – and it was challenging!

All modules so far were straight forward to implement and test, because they were quite independent of each other and had a defined interface. The scaler on the other hand is now the heart of the video output data path and needs to work in coordination with the deinterlacer, line FIFO and video output module to produce a frame. You can imagine how many possibilities for errors this introduces, if one gear is blocked for whatever reason, everything stops working. An additional difficulty in my architecture was that the scaler doesn’t have direct read access to the framebuffer – everything needs to be done via the deinterlacer & line FIFO and the scaler needs to read 4 pixels from 4 different addresses in parallel.

Horizontally this was made possible by implementing single port write / dual port read linebuffers, so 2 pixels could be read from different addresses within a line.
Vertically it was more challenging, because the scaler produces an absolute Y read address – but the line FIFO can only provide the next 5 lines to read from, relative from the current line in the output. I solved this by only calculating the relative Y increment from line to line, instead of an absolute address -> the tail pointer of the FIFO will be updated by that value. This is generally OK, as the scaler will either not increment or increment by 1 in case of upscaling. But when downscaling, it can happen that the line address increments by 2, so the FIFO will need to handle throwing out a whole line – this happens all the time when scaling PAL down from 512 to 480 lines. In this use case it works OK, but the implementation limits the amount of downscaling the scaler can perform before the everything breaks. Not that you would actually want to do downscaling, apart from 512->480.

Another difficulty was the calculation pipeline. Floating point numbers are not easily feasible in FPGAs, so I had to rely on fixed point numbers. Sadly, I could not find a widely supported standard library for VHDL, so my two options were to either use an open-source library or to do my own thing. Consistent with my design approach so far, of course I implemented my own freestyle fixed point calculations in the whole pipeline. I ended up going for 18-bit integers to fit the 18x18 multipliers present in the Trion T20, with 15 fractional bits.

Now I also finally feel confirmed for saving all hardware multipliers for the scaler – the T20 only has 36 in total and 19 are now used by the bilinear scaling pipeline

The whole implementation is already working for the most part – there are still some combinations of settings that can cause artifacts, but I’m debugging those right now. It turns out that the possibility to set any combination of configs in real time will uncover edge cases you never even thought about!

Current top level block diagram:
1745171203136.png

Current T20 resource utilization:
1745168588382.png


Testing and debugging:
Finding all settings with issues is actually quite easy now, as all settings are configurable from the menu:
->cycle through settings to find problematic combinations, write down the settings to debug, enter the affected settings in the test bench and debug from there!

Before I had to generate a new bitstream each time I wanted to test a setting on hardware, which is absolute misery. Probably the smartest approach would be to ditch the VHDL test benches and go for something like cocotb, but I’m not quite there yet. That would enable me to test every setting in simulation, without writing thousands of lines of VHDL test benches.
After testing the fixes in simulation it’s really easy to deploy a new bitstream to the hardware. I generate the bitstream, recompile the firmware, connect the portable and drag the new image onto it. I would consider this one of the smartest decisions I made when defining the hardware architecture – being able to reconfigure the FPGA via firmware. Otherwise, I would need to take apart the portable for every little fix and upload the new bitstream using the debugger. That was only necessary a handful of times for live-debugging one or the other nasty bug in the FPGA.

In the video below you get a short overview of the current state of the menu, as well as the newly added video configurations.
(sorry for the bad video quality again, it's really difficult to film displays!)


Overall thoughts:
Enabling scaling takes a hit on image sharpness, that’s clearly evident, even on such a tiny display. I guess one factor is the fact that the resolution of 480x800 is not much higher than the PS2’s output resolution, the impact would probably be less noticeable on higher output resolutions. It's also possible that there is still a bug in the pipeline...
If image sharpness is more important than scaling, the scaler can also be turned off by setting the output resolution to the input resolution. In that case the data is still pushed through the bilinear scaler pipeline, but the scaling factors are 1.
For PAL there is probably no way around scaling, so image quality will always be worse. Previously I was just discarding every 16th line which led to an overall sharper image, but the missing lines were very apparent in the output image. I guess in the end it’s a compromise. Maybe I will consider re-enabling the previous scaling approach for PAL to have both options.

Next Hardware Revision:
With the major video processor modules out of the way I’m pretty confident that the current mainboard architecture is sufficient to support all features I want to have. That’s why I started to work on the next and hopefully final mainboard revision in parallel. As mentioned already, the architecture will probably not change much, but I do have some important points to address:
  • Consolidate all power planes into one power layer instead of two. This is to reduce potential EMI issues when having adjacent power planes of different voltage. It was fine for the first revision, as the spacing was much larger, but with the JLC stackup it needs to be addressed. Rev. 0.2 featured a compromise to speed up development, but now I want to tackle this.
  • Further BOM consolidation. Rev. 0.2 improved this a lot already, but I still want to get rid of a lot of components. Especially resistor and capacitor values where only 1 or 2 components are needed for the whole board.
  • Bigger flash for the syscon. The 16Mbit flash is quite full already, as it also contains the FPGA bitstream. I’d like to reuse the 128Mbit flash of the SD2PSX in the future.
  • Simplifying routing. With one of the power planes gone, I have room to move the low-speed signals to an inner layer. Depending on the space maybe even high-speed stuff, but there I’m worried about power plane splits.
  • Adding more test points. During testing I found some signals where I would like to have a test point. I also know the function of a lot more EE, GS, DSP and MC pins now, some might be interesting to have on test points. (PPC UART for example)
  • Adding buffers on the HP_SENSE and BOOTSEL signals. The long traces for HP_SENSE (high impedance source) and BOOTSEL (possibility to introduce SI issues) make me feel uncomfortable, even though they work just fine in rev. 0.2.
  • I’m looking into replacing the mid mount USB A socket of the stock PS2 with something you can actually buy today, to reduce the number of components to be salvaged from a PS2.
  • The memory card flex connector needs bulk decoupling on VCC
  • I’m considering the option of making the USB C socket replaceable. That would add another PCB to the BOM, so I’m not sure yet.
  • I’m looking into better connectors for connecting the batteries. Soldering the wires to the mainboard is also an open option (reduce BOM count).
  • Some footprint adjustments for easier soldering
An improved SD SD2PSX was designed, including some of the points I mentioned previously. That will be ordered soonish.

Next point would be working on the Rev. 0.2 controller flex PCBs. The mechanical design was done already last year, but I didn’t start the layout yet.

Regarding the mechanical design, one of the upcoming tasks would be to adapt the heat spreader to the new mainboard design. I will shorten the depth of holes where it’s necessary to tap M1.6 threads to make tapping easier and to reduce the chances of breaking taps again. Another change would be related to thermals – I would like to increase surface area of the fins and increase the thickness of the material touching the EE, to make cooling a bit more efficient. Currently the EE settles at about 42°C @80% fan speed of the switch lite fan. Note that this is not comparable to a stock mainboard, as I decided to move the temperature sensor directly below the EE for more accurate temperature measurements. I think the temperature is OK, however I would like to reduce the fan speed a little (if possible). Luckily the fan curve is adjustable in the menu now, which makes testing easier!

Lowest priority is a new revision of the memory card flex, the only envisioned change there would be a footprint change of the VCC decoupling capacitor from 0402 to 0603.

Boot Rom Flex & PS2 Setup
Maybe a bit off-topic, but I managed to install a Noctua fan and the latest 64Mbit boot rom flex in my childhood 39k PS2, to finally start setting up my PS2 gaming setup for playing at home. The idea is to just remove the SD2PSX from the portable and to pop it into my fat PS2 to continue playing, which works really well!

For the boot rom I chose to do some light modifications: I added PS2BBL to the empty space at the end of the binary and added it to ROMDIR. Then I added a modified EELOAD module to launch into PS2BBL by default, eliminating the need for FMCB and making it compatible to the boot memory card I set up in the SD2PSX for my portable. The new boot rom flex keeps the DVD player fully functional, in case I ever watch DVDs on the thing (sometimes I do).

It’s coupled now to a Retrotink 5X, which I often use as a reference when debugging the video processor (not all image artifacts come from bugs, some show up in the RT5X too).
 
Top