kernelcrash / electron-rom-emulator

Emulate sideways ROMS and SD interface for Acorn Electron
https://www.kernelcrash.com/blog/emulating-a-hardware-rom-in-real-time-with-an-stm32f4/2018/05/27/
18 stars 4 forks source link

Electron ROM Emulator

kernel at kernelcrash dot com More details on this at www.kernelcrash.com

Overview

This interface is effectively a proof of concept for simple communication between the interupt and a main outer loop that runs on the stm32f4 board.

Currently there are eight memory addresses that correspond to the 8 rom slots;

   &FC04   - rom slot 4
   &FC05   - rom slot 5
   &FC06   - rom slot 6
   &FC07   - rom slot 7

   &FC0C   - rom slot 12
   &FC0D   - rom slot 13
   &FC0E   - rom slot 14
   &FC0F   - rom slot 15

Wiring

Technical

An older version of this program sat in a tight timing loop watching the phi0 output of the Electron. Phi0 is effectively the clock for the Electron. It is 'mostly 2MHz' but will slow down when accessing peripherals or RAM.

So that version watched for phi0 going high, read the address lines of the 6502, worked out if it was a sideways rom access, presented a byte from the STM32's flash rom, left it long enough on the databus for the 6502 to read it, then quickly tri-stated the databus again ... and waited for next rising edge of phi0.

This newer interrupt version connects phi0 to an interrupt on the STM32. Rather than interrupt on the rising edge of phi0 when the address bus would be known to be stable, the interrupt occurs on the negative edge of phi0 which is effectively the end of the previous cycle.

The reason for doing this is that it takes time to respond to an interrupt, so the latency between an 'edge' that causes an interrupt and the first executing line of an interrupt service routine (ISR) is at least 100ns, but more like 150ns ... but can be higher. If the first executing line of the ISR occurred 150ns after the positive edge, then it would be too late to do anything useful (the 100ns or so left is not a lot of instructions).

So we interrupt on the negative edge and the ISR routine goes like this;

Still this is a miniscule amount of time to service an interrupt. Key stuff:

You need the ST standard peripheral library. I used the STSW-STM32068 firmware package for the stmf4 Discovery from st.com. In the Makefile ST_COMMON needs to point to it.

You need an ARM GCC build chain in your path.

Generally you put your roms on the SD card, but there is way to load some from internal flash (see troubleshooting notes further down).

Do a

   make

Look at transfer.sh for how you might transfer it to your board.

Troubleshooting

If you have trouble with the roms loading from SD card , check a few things

Comment it out , and recompile.

Both methods are attempted on boot in the order shown above. So let's say you defined two ROMs in roms-preloaded-from-flash.S, and they were defined to load as slot 12 and 13. But it you also put a ROM in boot/12 on the SD card, then slot 12 would be overridden with what you had on the SD card. Similarly slot 13 would be overridden in you had a ROM in boot/13 on the SD card and so on.

To use preloading from flash, place the roms paths as incbin lines after the relevant slot labels in roms-preloaded-from-flash.S

      slot_4_base:
        .incbin "roms/ESWMMFS.rom"
      slot_5_base:
        .incbin "roms/AP6v130ta.rom"
      slot_6_base:
        //.incbin "roms/blank.rom"
      slot_7_base:
        //.incbin "roms/blank.rom"

Obviously 'make' and flash the hex file to the stm32f407 board to use these. (you might need to do a 'make clean' then 'make')

For reference the AP6v130ta.rom referred to above is the 16K AP6 rom from http://mdfs.net/Software/BBC/SROM/Plus1/ . That will give you a *ROMS command as well as various sideways ram load/save commands. I often put this as rom 13.