-
The RP2350 Dilemma
08/11/2024 at 01:24 • 0 commentsNew chip day (well a few days ago now)! And of all the chips it could be, there’s finally a successor to Raspberry Pi’s RP2040 microcontroller - the RP235x line.
While initial reactions appear mixed, with questions on whether the chip stands out from the competition (much like when the RP2040 was launched), I am firmly excited by the prospects the RP2350 offers - to the point I’m considering completely redesigning RetroMedleyCard around this chip…So what makes this chip so enticing that I would throw away much of the design effort that’s gone into RetroMedleyCard so far? After briefly reading through the datasheet, I’m convinced the RP2350 could stand as a single-processor solution for RetroMedleyCard, rather than the mixed ESP32-S3 application processor + RP2040 video coprocessor currently implemented, thanks to several upgrades bestowed upon the RP2350 compared to its predecessor:
- Each CPU has been bumped up from Cortex M0+’s @133MHz to Cortex M33’s @150MHz. While the clock speed has only seen a moderate bump, the new M33 cores should offer an appreciable increase in performance-per-clock cycle. Plus, according to dmitry.gr, the chip readily overclocks to 300MHz, so should give it plenty of grunt to run many of the same emulators which run on the ESP32-S3’s 240MHz LX7 cores at present.
- A second chip select on the QSPI memory bus allows an external PSRAM chip to be used alongside external flash, giving plenty of storage and memory for Retro-Go to work with.
- Increased on-chip SRAM to 520kB should allow double buffering of the entire display (153.6kB per 320x240 frame in RGB565)
- New peripherals which practically appear to be designed to enable DVI display output: Hardware TDMS encoders specifically designed to the DVI 1.0 specification - currently the RP2040 does this in software with help of the programmable IO’s; and a new High-Speed serial transmit (HSTX) peripheral, which can output up to 300MT/s @150MHz core frequency, on up to 8 pins, with controlled output delay to aid it’s use to implement differential drivers - which sounds perfect to output a DVI video signal from the TDMS encoded stream!
- The USB peripheral appears to be essentially backwards compatible with that of the RP2040. This will hopefully mean TinyUSB support will arrive shortly, which would be more portable than the USB Host Stack/Library in the ESP-IDF.
All of this is enticing as reducing RetroMedleyCard to a single processor-chip design will greatly simplify both hardware and software fronts. There will be no need to transfer frame data between processors, or to lay out multi-bit wide buses between chips, no need to store and upload code to the video adapter processor at runtime, no need to perform tight synchronisation between transferring pixel data and active region selection commands. Keeping all of this functionality contained in one chip, in one set of addressable memory, should just be easier.
That said, such a shift will still require a substantial amount of work. Aside from the fact the the PCB layout will essentially be reworked from scratch, I would also need to consider the difficulty of porting Retro-Go from the ESP-32 to the RP2350. At the very least, anything dependant on the ESP-32’s peripherals via the ESP-IDF will need to be rewritten for the chip. Additionally, the RP2350 requires PSRAM to be added to the QSPI bus, whereas the ESP32-S3 is available with internal PSRAM attached to an Octal SPI bus, potentially offering more memory bandwidth, which may end up bottlenecking emulator performance. There’s also a handful of minor issues that will need to be considered:
- The RP2350 lacks wireless support. While RetroMedleyCard theoretically support WiFi and Bluetooth, it is not supported in Retro-Go when using later builds of the ESP-IDF, but Netplay support and Bluetooth controller functionality would still be nice to have.
- Only a single USB Host port. Currently RetroMedleyCard exposes the USB peripherals of both the ESP32-S3 and RP2040, with the aim of implementing support for the ESP32 to control the RP2040’s USB peripheral at some point in the future for multiple controller/USB audio support. Since I’m betting on TinyUSB support for the RP2350, I’m hoping I can make up for this with robust USB hub support?
- Buck topology core regulator will require an additional inductor. A discrete chip inductor could potentially increase overall board thickness, while PCB inductors take substantial board area. However, since the core voltage can be regulated directly down from 5V, only the peripheral supplies will be dependent on the 3V3 rail, so the existing 3V3 buck regulator could be replaced with a linear, low dropout type?
I could go on and on about what I think of this new chip, but that would quickly get off-topic from its applicability to RetroMedleyCard. A sensible next step would be to put an RP2350 development board on order and grab the latest version of the SDK to see just how much work porting Retro-Go to the chip will entail, I could then decide from there whether a total redesign around an RP2350 is a viable approach going forward.
-
The 2024 Business Card Contest is almost over - what’s next?
07/01/2024 at 19:19 • 0 commentsWith less than 24 hours until the contest closes (assuming I’m getting my timezones right), I’m still surprised that I’ve been able to go from a half-baked idea to a nearly functional device in the span of about two months. That said, there’s still plenty more work to be done to get RetroMedleyCard to the lofty heights of “wafer-thin DOOM”, which then raises the question - what happens next?
Well first of all, I intend to take some time off to focus on getting some other (much simpler) projects across the finish line, and maybe even documented and shared if I’m happy with how they turn out. I’m also considering tidying up and releasing the simple_swd component I wrote for this project as a library, since it could be useful in other projects needing an easy way to access the SWD port of another MCU. Since the last two months have been especially stressful, getting RetroMedleyCard to where it is now, a change of pace and focus is in order…
When I do return to this project, the first port of call would be to address the glaring issues identified in the current RetroMedleyCard iteration, namely a lack of available RAM on the ESP32-S3, fiddly and unreliable PCB connectors, and any silly errors in the PCB layout.
Fortunately, the memory situation should be an easy fix, since Espressif offers the ESP32-S3-PICO-1-N8R8, with a whole 8MB of flash AND PSRAM. Since the current PCB doesn’t use the octal-SPI pins reserved for larger PSRAM devices, it should hopefully be a simple drop-in replacement for the current ESP32-S3FH4R2. I will need to read though the datasheet in detail, but it may be possible to reflow rework the existing PCBs for use as an initial test platform.
Fixing the PCB layout and connectors will necessitate a new PCB iteration, though I will probably want to get the more capable ESP32 SoCs soldered by the fab house anyway, so updating the PCB at the same time shouldn’t be an issue, I could even add actual contact details to the silkscreen and QR code!
The USB-C connectors will likely remain the same for iteration 2, as I still have a full batch worth of USB-C socket PCBs leftover. The 3.5mm TRRS audio socket should hopefully be relatively easy to fix, requiring a separate, dedicated PCB prong for the tip, due to its smaller diameter. The SD card socket can be improved by adding taller components as “pads” to contact the SD card, and relocating some of the pull-up resistors to act as physical barriers which prevent the SD card from being inserted too far. However, the current “pads” (0603 capacitors) are already theoretically the same thickness as the base PCB, so switching to taller components will increase the overall height of the card, which would be pushing the <=2.0mm target.
With the extra PSRAM available, it should be possible to get a much more complete firmware working on the second iteration, using knowledge gained trying to bodge retro-go onto iteration 1. Firmware modifications should be much neater, better targeted to achieve the desired functionality, and with helpful comments explaining what the changes do, so that it can be released alongside the revised hardware design files. This would aim to include functionality which was omitted from the first iteration, such as gamepad support, proper audio output, and the ability to run a larger range of emulators (including DOOM, fingers crossed!).
As for now, this concludes my work towards the 2024 Business Card Challenge, and I wish the best of luck to everyone participating! -
It just about works, but can’t run DOOM…
06/30/2024 at 02:00 • 0 commentsSo the last few weeks of trying to patch together some working firmware before the competition ends have been… eventful.
On the plus side, I did finally manage to get the card running an emulator, controlled over USB and displaying to a monitor via a HDMI port!
Robert Doman’s Space Crawler demo for Gameboy running in an emulator on the business card
However, there were a large number of difficulties along the way, and as a result I’ve had to make some pretty significant compromises (for this version of the board at least). As an overview of what works and what the limitations are (will be explained in detail later on):- Display - the DVI output itself works great, the PCB edge connector seems reliable and my monitor recognises the signal flawlessly. However, the speed of the QPSI bus has been limited to 16MT/s, for 64Mbps throughput, or 52fps at 320x240 resolution in RGB565.
- USB - The card is controlled entirely via the USB Host interface of the ESP32-S3, supporting only HID keyboards at present. The RP2040’s USB interface is not configured, and the data wires are the wrong way around on the PCB anyway! Additionally the PCB USB edge connectors are quite temperamental and requires some fiddling to get a reliable data connection.
- Retro-Go launcher - about the only thing that works flawlessly is the launcher application built into Retro-Go - probably because I didn’t need to modify it!
- Emulators - currently I’ve only been able to get gameboy emulation working under Retro-Go (though there are many emulators I haven’t tested yet). Other emulators crash immediately on startup, which I suspect is due to a lack of memory on the ESP32-S3
- DOOM - crashes immediately on startup, which again I suspect is due to limited system memory
- Audio output - Retro-Go appears to use the audio stream to govern the emulator speed, relying on the rate the DMA transfers samples to the I2S peripheral. I haven’t been able to get this to run without crashing, and naive attempts to drive the sigma-delta peripheral in software resulted in inconsistent game speeds and horrific sounding audio. So, audio is disabled for the time being :(
- “Sockets” - the audio and SD card “sockets” sort of work. Only certain SD cards actually make contact with the capacitor pads (presumably due to dimensional tolerances), and I misinterpreted a dimension drawing of the 3.5mm TRRS plug, so the tip fails to make contact in the “socket”.
So all-in-all, it mostly meets my requirements as a minimum viable demonstrator, but there is obviously a long way to go to reach what I originally envisaged when starting the project, and getting to this point at all required overcoming a bunch of hurdles in the development process, which at times felt like complete show-stoppers.
Getting a working display output
Going chronologically, the first major challenge was getting the RP2040 up and running as a video coprocessor, using the ESP32-S3 to program it on-the-fly.
I chose to keep the RP2040 firmware within the flash on the ESP32-S3, rather than on the SD card, as otherwise there would be no-way of seeing errors if the SD card wasn’t connected. UF2 format was used for this as it seemed to give the smallest firmware file (compared to the .bin and .elf files) while also being easy to read data from.
Difficulties started when trying to connect to the RP2040 over SWD. As mentioned in a previous log, the RP2040 uses a multi-drop SWD interface, which many examples of the SWD interface do not implement. I had been using ataradov’s embedded-swd library, with some modifications to try and generate the initialisation sequence needed for the RP2040’s debug interface. Unfortunately I never had any luck getting a response from the RP2040, and didn’t understand the code well enough to debug what might be wrong with it. So after a sleepless night coding my own bit-banged implementation of the SWD interface (as best as I understood it), simple_swd was born! Which then also promptly failed to connect to the RP2040. After some fiddling with the signal phases, I finally started receiving ACK’s over the SWD interface, and after some researching and copying from the PicoVision’s display driver, I was finally uploading and verifying firmware to the RP2040 successfully. I then never touched that part of the code again out of fear of breaking it.
Unfortunately the firmware itself for the RP2040 also proved to be a challenge. I had hoped to use the RP2040’s direct memory access (DMA) controller to elegantly stream pixels from the QSPI (via Programmable IO [PIO]) interface directly into the frame buffer. However, Retro-Go takes advantage of the ILI9341’s 2Ah and 2Bh commands, which allow it to restrict the region the in frame buffer that it writes to, This has the advantage that a partial display update doesn’t require transferring a full frame buffer to the display, however in my case I would need a way to configure the DMA on-the-fly according to the desired region in the frame buffer, which I simply couldn’t get working. I think this was due to issues synchronising when the CPU reconfigures the DMA channel, as this would need to occur after the DMA had finished transferring pixel data to the current region, but before the PIO buffers started overflowing with pixel data for the next region. This led to lots of interesting graphical artefacts, such as below:
Misalignment of UI elements when trying to use DMA driven frame-buffer. Navigating the menu could also result in discolouration of the image, similar to the 20MHz bus, CPU driven case. Image taken after getting everything else working as a demonstration.
In the end, to resolve this I resorted to directly using the CPU to move pixels into the frame buffer, making it easy to update the display region only once the current stream of pixel data had ended. This “works”, but has a far lower bandwidth than the DMA could offer, and I had to lower QSPI transfer rate all the way down to 16MHz before artefacts were no longer present. At 320x240, 16bpp this gives a maximum theoretical frame rate of ~52fps
Discolouration of image observed when using CPU driven frame buffer transfers at a 20MHz bus frequency. Image taken after getting everything else working as a demonstration.
Dropping the QSPI frequency down to 16MHz results in correct image rendition when using CPU driven pixel transfers to the framebuffer. Image taken after getting everything else working as a demonstration.
Booting into an emulatorWith a passable display output, the next hurdle was to actually navigate the launcher and load up an emulator to test.
Of course, as soon as the card started up I was greeted with a convenient “Failed to mount SD card” screen, and no amount of fiddling with the SD card adapter or the PCB “Socket” would change that. All logs on the console simply gave time out errors, meaning a frustratingly possible cause was that the card simply wasn’t making contact in the “socket”, and without any working input on the business card I had no way of dismissing this error to see if the boot process got any further.
Taking the USB HID host example from the esp-idf, I threw together a quick component to receive input over USB HID, and after some messing about with the code, updating partition table configurations (adding the USB stack meant some apps became too large to fit in the default 1MB partition size) and fiddling with the awkward USB PCB edge connector, I was eventually able to use a USB keyboard as a controller to skip past the error screen.
Finally past the error screen and into the launcher!
Then, while looking for supplies to try and bodge the SD card “socket”, I dug up another SD card which happened to be recognised right away! Presumably the pads on this card were recessed slightly less, so were able to make contact with the pads of the “socket”.
So now that there is working display output, SD card storage and keyboard input, what else is there to do than try running DOOM?System panic trying to launch DOOM on the business card
Oh.
Maybe try another emulator?
Nope, still crashes.
Gameboy should be easy enough to run, right?
Emulated Gameboy demo running on the business card
Success!As to why other emulators seem to crash on startup, my current guess is lack of memory, and the Gameboy emulator is the only one I’ve been able to get running so far (though there are many emulators in retro-go that I haven’t tried yet). For a microcontroller, 2MB of RAM seems like quite a bit, but compared to the systems we’re trying to emulate, even a Gameboy Color ROM takes the entire 2MB, leaving no memory for the system to actually run! Other targets for retro-go all seem to have 4MB of PSRAM or more, so having only 2MB is probably pushing it.
Audio performance woes
While the card has demonstrated being able to run an emulator, unfortunately the initial performance is dreadful. This seems to be due to my naïve implementation of audio output using the sigma-delta modulator peripheral on the ESP32-S3, which blocks the CPU between each audio sample, when it could be updating the emulator state. In retro-go, the emulator speed is governed by the time taken to output a buffer of audio samples, which normally uses the DMA feature of the I2S peripheral to copy audio samples independently from the CPU, relying on the time taken by the DMA to finish transferring a buffer of audio samples (at the specified sample rate) before starting the next emulator tick.
for (size_t i = 0; i < count; i++) { //Get volume float volume = audio.muted ? 0.f : (audio.volume * 0.01f); //Scale frame outputs by volume int16_t left_16 = frames[i].left * volume; int16_t right_16 = frames[i].right * volume; int8_t left_8 = left_16 >> 8; int8_t right_8 = right_16 >> 8; //Update sdm channels sdm_channel_set_pulse_density(sdm_chan_l, left_8); sdm_channel_set_pulse_density(sdm_chan_r, right_8); //@TODO: Quick and dirty sleep to next audio frame rg_usleep( (uint32_t)(1000000.f / audio.sampleRate) ); }
Naïve audio output implementation which blocks the CPU between samples. This forces the emulator state to be updated only after all the audio samples have been played, resulting in choppy sound and performance
In my memory limited scenario, trying to use the I2S audio with DMA causes even the Gameboy emulator to immediately crash, presumably due to insufficient memory to store the audio buffers. This probably isn’t helped by the inclusion of the USB Host stack, either.
So, for the time being, I have decided to replace the audio output with a delay loop controlled by the system timer, giving buttery smooth (albeit silent) performance. While it is disappointing to lose audio output, the stuttering of the emulator and audio output resulted in a terrible experience, and getting smooth gameplay even without audio is significantly better to play. Future versions of the card will inevitably need to have more memory to allow other emulators to run, which should also allow proper DMA controlled audio output to be enabled.int64_t audio_period_us = count * (1000000.f / audio.sampleRate); int64_t audio_end_time = last_audio_time + audio_period_us; while((rg_system_timer() - audio_end_time) < 0) { asm("nop"); } last_audio_time = audio_end_time;
Delay loop used to replace audio output. This is governed by a system timer that runs independently from the CPU, so everything runs at a fixed frequency regardless of of how long each emulator tick takes.
-
Hardware is here!
06/12/2024 at 01:51 • 0 commentsFirst set of boards are finally here, so soon I should be able to start testing software!
Assembled board front view
Assembled board rear view
The boards were ordered with PCBA for most of the surface mount components, largely due to the use of DFN/QFN packages which would be difficult to solder without reflow. The flexible connector “prongs” had to be separated from the edge of the PCB (shown below) and soldered onto the front of the card, forming the contacts for the SD card and 3.5mm Audio Jack. Additionally, a handful of passive components forming the crystal oscillator and RF filter still needed to be assembled, as the specific component values required additional fees for SMT assembly. (Shoutout to my dad for helping assemble these while I’ve been trying to write firmware!)
Board as shipped. Note the prong structures attached to the bottom of the board which are removed and soldered to the front of the PCB to act as flexible contacts.
The unusual connector designs actually appear to work better than I expected, though I’m not entirely convinced the SD card and 3.5mm jack are making good contact. Nevertheless, It looks good for a first version and should be bodge-able if they prove problematic. Due to the small profile, I chose to omit the cutouts in the sides of the USB-C plate, which would normally provide a latching action, so that they would be easier to mill. Fortunately there still seems to be enough friction to provide a decent retaining force, and the (H)DMI connector also stays seated without too much fuss.
Assembled board demonstrating the use of the many silly connectors it incorporates. Much to my surprise, the PCB prongs seem to hold up quite well to being flexed when inserting/removing the SD card and Audio plug.
In the meantime, I’ve been focusing on trying to get an initial firmware to a state where it can be uploaded to test that the board is actually functional. In particular I’ve been trying to understand how the Serial Wire Debug (SWD) interface of the RP2040 works such that I can upload a program into RAM from the ESP32.
As it turns out, the SWD interface is actually quite simple, while the documentation (in my opinion) makes trying to understand it seem like a chore. Eventually, I stumbled across this application note by Silabs, which gives a fairly concise explanation. To keep things brief, each transaction essentially consists of an 8-bit request followed by an acknowledgment and 32-bits of data read/write. The request can read or write to one of four registers on the debug port to control it, such as to select an access port to the system’s resources. The access port is then controlled using the same request format to manipulate registers to access system memory, etc.
Aside from a few nuances (inserting an extra clock cycle to change data direction, clocking an extra 8 bits after the last transaction to ensure it is fully cooked through the debug port) this forms 99% of transactions over SWD. Initialisation of the debug port seems to be an exception, which requires specific sequences of bytes to be transferred to reset and enable the interface.
The RP2040 specifically implements a multi-drop bus, allowing multiple targets to be connected, This seems to be a feature of “SWDv2”, which also implements some additional registers that were reserved in v1. This also requires a different initialisation sequence compared to v1, so documentation that does not refer specifically to multi-drop/SWDv2 is likely for the older v1 interface, and probably won’t work the the RP2040!
What would be nice now would be an easy-to-use, high level library to bit-bang either version of the SWD protocol, to make using the RP2040 as a flash-less coprocessor easier, for applications acting as an IO expander, to provide additional interfaces, or even to allow other architectures to use the RP2040 PIOs? This could also support more capable successors to the RP2040, should Raspberry Pi ever release more microcontrollers. Maybe someday I will try to write such a library, should I have the time and can resist the urge to procrastinate!
-
Software scope
05/30/2024 at 20:41 • 0 commentsWith the board out for manufacture, I now have some time to start thinking about how I'm going to get code written for it. Given the range of potential features available on the board (WiFi, Bluetooth, 2x Usb Hosts, DVI video, "analogue" audio), and the short time span of the competition, I don't want to be stuck-in over my head rushing to get the code working in time. Instead, I would like to create a minimum viable demonstrator for the competition, illustrating the core functionality of the project, then fleshing out all the extra features at a later date.
Features that i consider to be part of the "core" functionality, against nice-to-haves are tabulated below:
Required features Nice-to-have features Support for a single external gamepad Support for multiple external game pads over a range of interfaces Unbuffered video output through DVI in RGB565 Fully buffered or syncronised video output to prevent tearing with up to 24-bit colours Analogue audio output over 3.5mm Jack Audio output over a range of interfaces Playable emulator Range of playable emulators with launcher(s) The core functionality revolves around the minimum requirements to reach the point where *an* emulator is playable on the card, while nice-to-have features expand on capabilities to support emulation of multiple devices, using a range of input devices and flexible audio output selection depending on user preference.
These nice-to-have features result in a more complete device, but adds multiple cases will need to be handled by the software and be debugged, which could considerably increase development time.
As previously mentioned, I would like to port Retro-Go to this card which should handle launching and running various emulators, so I would otherwise mainly need to focus on adding support for the various interfaces: a gamepad driver using Bluetooth OR USB host on the ESP32, DVI video through the RP2040 coprocessor, and audio output using the ESP32's sigma-delta modulator.
Once these features are working well, I can evaluate whether to throw in some of the nice-to-haves, or move straight onto documentation and tidying things up, depending on how much time remains in the competition (if any!)
-
Retroactive log 3: Hardware design and features
05/30/2024 at 20:07 • 0 commentsWith an overarching plan established to set the direction of the design, it's time to actually produce a PCB layout and determine all the little ancillary components to support the main processors.
So, following a hectic bank holiday weekend stuck in front of KiCAD and countless datasheets, I eventually managed to cram everything onto this board:
To give a quick overview of the specs:
- ESP32-S3 application processor with 4 and 2 MB of on-package flash and PSRAM, respectively
- RP2040 video adapter, connected to the ESP32 via QSPI at up to 320Mb/s, and a second full duplex SPI side-channel at up 80Mb/s (in theory)
- PAM8908 stereo headphone amplifier, chosen for being able to operate on a single supply rail without needing a bulky output capacitor
- Dual USB 2.0 hosts over USB-C (connected to the ESP32 and RP2040, respectively), using AP22653's as power switches with ~750mA current limit
- Full size SD card slot over 1-bit SDMMC interface on ESP32
- TLV62585 synchronous buck converter to power it all.
The board itself has a number of "interesting" design choices baked in to keep profile and cost to a minimum:
- Card edge connector on top-left adapted from peterburk's picoDVIEdge should fit into a HDMI connector without using a chunky socket
- Direct soldered 0.6mm thick USB-C 2.0 socket boards using 8-pin, 2.0mm pitch through hole interfaces
- "Novel" SD card and 3.5mm sockets using flexible PCB prongs (seen at the bottom of the board) which will be sawn off and soldered directly to matching headers on the card.
- For the 3.5mm socket, a cutout in the board slightly smaller than the 3.5mm jack is used to keep it in place. The prongs are laid perpendicular to the jack, and press down on it to make direct contact with the rings while providing some retaining force
- The SD card prongs are aligned with the contacts on the card, and each uses 0.8mm tall capacitors as pads to (hopefully) interface with the recessed contacts of the SD card. Cutouts for the capacitors allow the prongs to remain flat on the board when no card is inserted.
- 2-layer PCB coil for the buck converter - adds no thickness to the design, is free, and looks cool! (Though an SMD chip inductor would probably be far more practical...)
- Entire board uses only 2-copper layers, to take advantage of discount pricing offered by several PCB fabricators
- Where traces have needed to be routed through the ground layer, I've tried to avoid routing underneath high speed traces (particularly the 40MHz QSPI and 80MHz SPI interconnects). These are then fenced with vias to a top layer ground pour, to try and bridge the ground plane over them. Hopefully this will ensure ground return paths are fairly uninterrupted.
- "Analogue" audio produced by the ESP32's sigma-delta modulator, passed through a first order RC low pass filter. This will probably sound "not great", but with only 2 passive components per channel it's also very cheap and compact.
- CC detection and power control on USB-C downstream facing ports to be handled in software on the RP2040. This allows common power switch ICs to be used, which were cheaper than any USB-C DFP controllers I could find. A mosfet on each CC line protects the RP2040 GPIOs from current injection when unpowered and another host is connected, or if connected to a host that pulls the CC line to +5V.
Putting all this together results in a board which should have no components taller than the 0.9mm-ish tall QFN packages, resulting in a total thickness of only 1.7mm!
With all the questionable features implemented, it's just a case of sprucing up the silkscreen and sending it off to be manufactured (no points for guessing where though!)
As it turns out, PCB art is hard, and not yet in my acquired skill set, so I instead resorted to using this cool font "AmazDooM" uploaded by Amazingmax. Thanks!
-
Retroactive log 2: Inspiration and The Plan(tm)
05/30/2024 at 00:33 • 0 commentsThis project wouldn't be a medley if it didn't draw inspiration from a number of other projects to solve niche problems raised only due to self-imposed restrictions, so here I "briefly" present a plan which forms the backbone of the design, and try to credit those sources of inspiration that make this project possible/plausible(?).
As mentioned previously, I would like to be able to run a number of emulators with support for external gamepads on a host microcontroller. I have chosen to use the ESP32-S3FH4R2, as it provides common connectivity options for gamepads (USB host, bluetooth), comes with flash and PSRAM on package, saving the difficulty of trying to fit these on a small PCB, and is proven to have sufficient performance to run several emulators such as via Retro-Go, which I would like to port onto this board to save the effort of writing firmware from scratch. To keep the form-factor as thin as possible, system-on-modules such as the ESP32-S3-WROOM are out of the question, so I will have to figure out how to integrate the WiFi antenna directly onto the board.
The RP2040 video adaptor will work using the PicoDVI library to bit-bang a DVI interface, which many projects and products have demonstrated before. The specific application of the RP2040 as a video adaptor for a host processor can be seen in Pimoroni's PicoVision development board (referring to the humble RP2040 as the 'GPU', heh), which appears to program the 'GPU' from a host Pi Pico using 2 GPIOs to emulate an SWD interface. I intend for my ESP32 host to do much the same, so seeing how the PicoVision firmware handles this should make things much easier.
While the PicoVision switches between two external banks of PSRAM as framebuffers, this sounds pricey and requires extra board space. Instead I aim to use the ESP32-S3's QSPI interface to shuffle data to the RP2040 as quickly as possible. Using a 4-bit bus in double data rate mode @40MHz gives a throughput of 320Mb/s, which should be more than enough to transfer a 320x240 framebuffer @60Hz (assuming the PIO on the RP2040 can handle it)?
To keep the form factor thin, I sought out some 'alternative' connector solutions that other have tried, and the findings are fairly hopeful!
USB-C 'ports' have been implemented a few times as PCB edge connectors, seen in Chris' CRAPi2040 (0.6mm thick PCB) and Dmitry Grinberg's Linux Business Card (0.8mm thick PCB), while picoDVIEdge by peterburk (0.8mm thick PCB) does the same to a 'DMI (the H is silent)' socket
While the 'DMI' connector appears to work well on a 0.8mm board, comments online seem to suggest 0.6mm would be more suitable for USB-C, so I plan to use a 0.8mm thick PCB as the 'base' of the card (as the 0.8mm option is cheaper), with small 0.6mm thick USB-C adapter boards soldered on.
A final big source of inspiration came from Dennis Kaandorp's PCB business card, which uses flexible prongs in a 0.8mm thick PCB to create a 2032 coin cell holder. With some creativity, I think this could be adapted create sockets for a 3.5mm TRRS connector and some form of external memory card (SD card or MMC)
Since the ESP32-S3 is quite power hungry and the RP2040 will need to be overclocked, a 5V-3.3V buck converter seems more appropriate than a linear regulator, especially in low profile packages which tend to have poorer thermal conductivity. This does mean finding a sufficiently low-profile inductor (e.g. chip inductors), or I could try designing the inductor coil directly in the PCB traces... for fun of course :) .
So summing this all up, the plan boils down to:
- use an ESP32-S3 chip (not a complete module!) as the application processor
- connect to the RP2040 video adapter through the QSPI bus, program from ESP32 via bit-banged SWD
- use a 0.8mm base PCB as it is economical and appears to fit into a HDMI connector
- use smaller, directly soldered 0.6mm PCBs to create 'sockets' for USB-C connections
- figure out ways that flexible PCB prongs can be used to support an audio connector and external memory card
- use a buck converter rather than linear regulator to reduce likelihood of overheating the chip due to need for a low-profile package
-
Retroactive log 1: Ideas and kickoff
05/29/2024 at 23:12 • 0 commentsWith the 2024 business card contest kicking off, I've finally found an excuse to try a silly project idea I came up with a while ago - making a big-screen compatible retro games emulator by using an RP2040 as a low-cost display adaptor through the PicoDVI library by Wren6991, coupled with a host micro-controller to actually run some emulators, using firmware such as ducalex's Retro-Go.
To keep costs, part-count and board space down, the RP2040 would have the bare minimum of components required to operate - no external flash/RAM, and clocked directly from the host processor. As the RP2040 lacks on-chip flash to store user programs, the host processor will need to upload firmware directly to the RP2040's RAM on startup.Since this is expected to be plugged into a monitor, having the controller built-in to the PCB wouldn't be particularly practical, so external gamepad support is a must, and we'd need audio too, of course.
To meet the competition requirements, this will need to fit on a small business-card sized PCB, and with a bonus category to make the product as thin and business-card like as possible, I get to try out some unusual workarounds to avoid using bulky components like connectors.
So in the two months the competition runs for:
- The PCB will need to be designed, manufactured and assembled
- Software will need to be written/adapted and *debugged* for both the host MCU and the RP2040
- Everything needs to be written up in a somewhat-orderly fashion
...which sounds an awful lot for such a short timescale...