{"id":1545,"date":"2021-03-12T19:55:09","date_gmt":"2021-03-12T19:55:09","guid":{"rendered":"http:\/\/retroramblings.net\/?p=1545"},"modified":"2021-03-12T19:55:09","modified_gmt":"2021-03-12T19:55:09","slug":"selecting-uploading-a-rom","status":"publish","type":"post","link":"https:\/\/retroramblings.net\/?p=1545","title":{"rendered":"Selecting &#038; Uploading a ROM"},"content":{"rendered":"\n<p><strong>Porting a Core, DeMiSTified &#8211; Part 6 &#8211; 2021-03-12<\/strong><\/p>\n\n\n\n<p>When I created a ZPU-based control module for the MSX and PC-Engine cores way back when, I created a menu system which used a tree of static menu structures, in which each elements could be one of several types.<\/p>\n\n\n\n<p>I supported function callbacks, checkmarks, cycles and even sliders.  It worked fairly well and the footprint was reasonably small &#8211; but it doesn&#8217;t lend itself to building a menu dynamically.<\/p>\n\n\n\n<p>In order to build an arbitrary menu from a MiST config string using this system I would need to support memory allocation, which means managing a memory pool, and if the menu ever needs to be re-generated, potentially dealing with fragmentation.  Doing any of this without bursting through the self-imposed 12k limit is unlikely to happen!<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>So instead I&#8217;m borrowing a trick I used from the file-selector in my previous project &#8211; where I had one page of the static menu structure declared and &#8220;filled in&#8221; on the fly.  As you scroll down the list, the file selector will simply re-scan the directory and discard the first &#8216;n&#8217; entries.  This has two serious limitations; firstly, sorting the files isn&#8217;t possible, and secondly, it could potentially slow down as you approach the end of a large directory.<\/p>\n\n\n\n<p>I can&#8217;t think of a good way to deal with sorting directory entries that won&#8217;t require way more RAM than we have available, or be intolerably slow &#8211; however one way to approach it is simply to collect the files together on a PC before copying them to SD card.  If you copy them en-masse to a new directory, then the file selector will see them in the same order in which they were copied.  For this reason I&#8217;m content to ignore the file sorting problem for now &#8211; I can revisit this at a later stage if firmware space allows.<\/p>\n\n\n\n<p>For dealing with dynamic menus created from MiST config strings, I&#8217;m using a similar approach.  Every time the menu is displayed or scrolled, I fetch a fresh copy of the string from the core, and in displaying it I skip the first &#8216;n&#8217; entries, to allow scrolling.<\/p>\n\n\n\n<p>What I haven&#8217;t yet decided is how I&#8217;m going to approach fetching ROM-specific options when I come to port arcade cores.  Since the menu-building code currently begins the SPI transfer of the config string, then fetches bytes one by one while building the actual menu, one option is to begin a file transfer, then allow the self-same code to transfer a sector of the file one byte at a time.  The actual menu-building code could then be (almost) independent of where the config string&#8217;s coming from.<\/p>\n\n\n\n<p>So having implemented a menu both for adjusting options and selecting files, we now need to perform the actual file upload.<\/p>\n\n\n\n<p>The MiST framework has a well-defined interface for this, in the form of the data_io module.  This has its own SPI &#8220;chip select&#8221; signal, and responds to three commands.  One enables or disables data transfer, one sets the &#8220;index&#8221; of the ROM (derived from its file extension, and which menu item was used to load the ROM) &#8211; which allows the core to handle ROMs of different types and automatically remap them appropriately &#8211; and finally a command to perform the actual data transfer.<\/p>\n\n\n\n<p>Sounds simple enough, yes?<\/p>\n\n\n\n<p>No.<\/p>\n\n\n\n<p>When I said that the MiST framework has a well-defined interface for ROM transfer, I was only telling half the story; in truth it has *two* such interfaces!<\/p>\n\n\n\n<p>In the interface I just described, the MiST board&#8217;s control CPU loads the data from SD card, one sector at a time, then passes that data to the FPGA core.  Both the FPGA and the SD card are on the same SPI interface; the control CPU&#8217;s data-out is connected to data-in on both the SD card and the FPGA.  Both the FPGA and the SD card have a data-out signal which is connected to the control CPU&#8217;s data-in.<\/p>\n\n\n\n<p>This implies, of course, that the SD card&#8217;s data out is connected to the FPGA&#8217;s data out, since they both go to the same pin on the control CPU.<\/p>\n\n\n\n<p>Some MiST cores exploit this fact, and employ a &#8220;direct&#8221; mode to speed up ROM loading (a trick which was inherited from the original Minimig&#8217;s disk support) &#8211; the FPGA pin that usually handles SPI data-out temporarily becomes data-in, which allows the FPGA to capture data directly from the SD card.  The control CPU is still generating the SPI clock, but it doesn&#8217;t have to receive and then relay the data to the FPGA &#8211; instead it coordinates a direct transfer.<\/p>\n\n\n\n<p>This is why some MiST cores define the SPI_DO pin as bidirectional &#8211; and this complicates matters.  Because we&#8217;re moving the external CPU into the FPGA design itself, we need to replicate the logical interconnections between the SD card and the guest core &#8211; but bidirectional signals in an FPGA are only allowed if they connect to a toplevel pin.<\/p>\n\n\n\n<p>What this means in practice is that if we want to adapt and wrap a MiST core which uses this bi-directional trick, we can&#8217;t leave the guest core completely unmodified &#8211; we will have to replace this bi-directional signal with a pair of signals, one for each direction.<\/p>\n\n\n\n<p>In other words, we&#8217;re replacing:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">   input         SPI_DI,  \/\/ Data from the MCU<br>   inout         SPI_DO,  \/\/ Data to the MCU, or from the SD card<\/pre>\n\n\n\n<p>with: <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">   input         SPI_DI,    \/\/ Data from the MCU <br>   input         SPI_SD_DI, \/\/ Data from the SD card<br>   output        SPI_DO,    \/\/ Data to the MC<\/pre>\n\n\n\n<p>In the toplevel we connect SPI_DI to a signal called spi_toguest, SPI_DO goes to spi_fromguest, and SPI_SD_SI is connected to the MISO pin on the SD card, and internally replaces the connection to SPI_DO on the data_io module.<\/p>\n\n\n\n<p>All that remains is to multiplex the control module&#8217;s spi input between spi_fromguest and the SD card&#8217;s MISO pin, depending upon the SD card&#8217;s chip select.<\/p>\n\n\n\n<p>Unfortunately the need for this workaround to bidirectional signals means that (a) the board specific toplevels can&#8217;t be universal, and (b) the guest core requires modification.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Porting a Core, DeMiSTified &#8211; Part 6 &#8211; 2021-03-12 When I created a ZPU-based control module for the MSX and PC-Engine cores way back when, I created a menu system which used a tree of static menu structures, in which &hellip; <a href=\"https:\/\/retroramblings.net\/?p=1545\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,8],"tags":[],"class_list":["post-1545","post","type-post","status-publish","format-standard","hentry","category-fpga","category-hardware"],"_links":{"self":[{"href":"https:\/\/retroramblings.net\/index.php?rest_route=\/wp\/v2\/posts\/1545","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/retroramblings.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/retroramblings.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/retroramblings.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/retroramblings.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1545"}],"version-history":[{"count":2,"href":"https:\/\/retroramblings.net\/index.php?rest_route=\/wp\/v2\/posts\/1545\/revisions"}],"predecessor-version":[{"id":1548,"href":"https:\/\/retroramblings.net\/index.php?rest_route=\/wp\/v2\/posts\/1545\/revisions\/1548"}],"wp:attachment":[{"href":"https:\/\/retroramblings.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/retroramblings.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/retroramblings.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}