Bare Metal ZX81 emulator


31 posts   Page 1 of 2   1, 2
by gertk » Sun Oct 28, 2012 11:22 pm
Just to get the hang of this Bare Metal stuff I ported my mbed ZX81 emulator to the Pi :)
No SDcard or USB keyboard yet alas..

A (ZX81) program binary can been uploaded through the serial port (xmodem) and keyboard emulation is a crude serial to ZX keyrow conversion.

Need a Vsync or other 50/60 Hz time reference.

very_small_2012-10-28 18.19.51.jpg
Hello world in ZX81 Basic
very_small_2012-10-28 18.19.51.jpg (26.33 KiB) Viewed 3661 times
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by hermanhermitage » Sun Oct 28, 2012 11:44 pm
gertk wrote:Just to get the hang of this Bare Metal stuff I ported my mbed ZX81 emulator to the Pi :)
No SDcard or USB keyboard yet alas..


Outstanding work!

I've been thinking it would be good to round up the troops and create some bare metal libs hosted on github for:
USB
SD
VideoCore services (now the user land is released)

of course resource management (task, interrupt, processes, memory) is a little tricky to do in a neutral manner. Any takers?
Posts: 65
Joined: Sat Jul 07, 2012 11:21 pm
Location: Zero Page
by jackokring » Mon Oct 29, 2012 12:29 am
I bet it's fast. I hope you take advantage of the multiple of memory to do a lot of pre-decoding of the Z80 bytecode. :) I suppose cross compiling it to ARM code in 4* the bytes could be expensive in memory? The nightmare of self modifying code with entry to the instruction stream half way through an opcode for multiple use. :lol:

Does the display disappear as you run out of memory?

EDIT: Just need the write byte routine to set the 32 bit call to decode byte, fix 32 bit arm code and return routine. Is this write penalty worth the execution decode elimination on static code?
Pi=B256R0USB CL4SD8GB Raspbian Stock. https://sites.google.com/site/rubikcompression/strictly-long https://dl.dropboxusercontent.com/u/1615413/Own%20Work/Leptronics.pdf https://groups.google.com/forum/#!topic/comp.compression/t22ct_BKi9w
User avatar
Posts: 784
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
by jackokring » Mon Oct 29, 2012 1:11 am
hermanhermitage wrote:of course resource management (task, interrupt, processes, memory) is a little tricky to do in a neutral manner. Any takers?

I won't take to the coding, but you could do worse than virtual machines for this king of stuff. This solves task, process and memory. With maybe a few extra keywords (or reuse of unused ones LPRINT etc), to evaluate an expression in a foreign context. Interrupts could be multiplexed by using the foreground machine as master, and any new master may override any GPIO pin for example, on ending or view switch an old master releases any pins used by the new master (even ones the new master opened and did not close ages ago). If new contexts could be created just by using one programatically by name (or #number), then extra memory could be used by creation of a new machine context, and population of it's variables. This all makes for a co-operative task switch on display memory update, with priority given to the front most virtual machines.
Pi=B256R0USB CL4SD8GB Raspbian Stock. https://sites.google.com/site/rubikcompression/strictly-long https://dl.dropboxusercontent.com/u/1615413/Own%20Work/Leptronics.pdf https://groups.google.com/forum/#!topic/comp.compression/t22ct_BKi9w
User avatar
Posts: 784
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
by hermanhermitage » Mon Oct 29, 2012 1:23 am
jackokring wrote:
hermanhermitage wrote:of course resource management (task, interrupt, processes, memory) is a little tricky to do in a neutral manner. Any takers?

I won't take to the coding, but you could do worse than virtual machines for this king of stuff.


Not what I'm suggesting at all.

Instead I'm suggesting a policy agnostic library in C and assembler for re-use in different bare metal and OS projects. The key points (1) being C and asm are widely available and require minimal hosting and it's a well trodden path, and (2) there is only so much fun in raw SD, Ethernet and USB lower level layers - its ripe for re use to allow everyone to get on with the things that do excite them, like a Scheme based OS or a vintage emulation OS etc.

The skill is in the balancing act of setting up the hooks so the same raw code can be hosted in a suitable form for drivers across a range of OS from Linux to RISC OS to Tufty's or Dex's work etc.
Posts: 65
Joined: Sat Jul 07, 2012 11:21 pm
Location: Zero Page
by jackokring » Mon Oct 29, 2012 1:49 am
hermanhermitage wrote:
jackokring wrote:
hermanhermitage wrote:of course resource management (task, interrupt, processes, memory) is a little tricky to do in a neutral manner. Any takers?

I won't take to the coding, but you could do worse than virtual machines for this king of stuff.


Not what I'm suggesting at all.

Instead I'm suggesting a policy agnostic library in C and assembler for re-use in different bare metal and OS projects. The key points (1) being C and asm are widely available and require minimal hosting and it's a well trodden path, and (2) there is only so much fun in raw SD, Ethernet and USB lower level layers - its ripe for re use to allow everyone to get on with the things that do excite them, like a Scheme based OS or a vintage emulation OS etc.

The skill is in the balancing act of setting up the hooks so the same raw code can be hosted in a suitable form for drivers across a range of OS from Linux to RISC OS to Tufty's or Dex's work etc.


Each library needs OPEN, CLOSE, TXRX functions. TXRX accepts a command string, the contents of which are the command language of the interface. So construction of the command language is the abstraction. In fact one function call TXRX is needed, and open and close can be done on first and last use. Device selection could be part of the IO language.
Pi=B256R0USB CL4SD8GB Raspbian Stock. https://sites.google.com/site/rubikcompression/strictly-long https://dl.dropboxusercontent.com/u/1615413/Own%20Work/Leptronics.pdf https://groups.google.com/forum/#!topic/comp.compression/t22ct_BKi9w
User avatar
Posts: 784
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
by hermanhermitage » Mon Oct 29, 2012 3:04 am
jackokring wrote:
Each library needs OPEN, CLOSE, TXRX functions. TXRX accepts a command string, the contents of which are the command language of the interface. So construction of the command language is the abstraction. In fact one function call TXRX is needed, and open and close can be done on first and last use. Device selection could be part of the IO language.


Suggest you post a link to your proposed solution on GitHub rather than spamming the forums - I'm sure I'm not the only one with frayed patience to these endless incoherent and Ill explained ideas.
Posts: 65
Joined: Sat Jul 07, 2012 11:21 pm
Location: Zero Page
by gertk » Mon Oct 29, 2012 7:21 am
jackokring wrote:I bet it's fast. I hope you take advantage of the multiple of memory to do a lot of pre-decoding of the Z80 bytecode. :) I suppose cross compiling it to ARM code in 4* the bytes could be expensive in memory? The nightmare of self modifying code with entry to the instruction stream half way through an opcode for multiple use. :lol:


At the moment I just copied the C source of my mbed project and, sorry to say, but at the moment the mbed ZX81 emulator runs rings around the Pi in terms of speed (I manage over 4 times original ZX81 speed on the mbed @ 100 MHz, that is with heavy DMA going on to generate VGA output on the I2S bus output) Ofcourse on the Pi I have to push more data to emulate the screen. I am using 16 bpp now. On the mbed I generate the complete pixeldata from the ZX81 DisplayFile memory on each Vsync and it can keep up easily. On the Pi I have setup a simple counter variable which counts Z80 opcodes and after n opcodes it generates the display from the ZX81 DisplayFile memory. I'm not sure if the display routine is the culprit or the Z80 emulation compiled by gcc is a lot slower than when using the mbed compiler. The emulator on the Pi is doing 4 to 5 frames per second...

Does the display disappear as you run out of memory?

Yes it still does :D Hey, it is a feature not a bug.. ;) Albeit, on a 16k ZX81 you almost never see that happen..
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by DrPinball » Mon Oct 29, 2012 6:40 pm
I (think) I got VSync working by...

Adding the following to config.txt...
fake_vsync_isr=1

This forces an interrupt 48 SMI for VSync event.

Enable interrupts for SMI...
Code: Select all
   ldr r0, =0x2000B214
   ldr r1, =0x00010000
   str r1, [r0]


Reset the interrupt just in case...
Code: Select all
   /* Reset interrupt via SMICS register */
   ldr r0, =0x20600000
   mov r1, #0
   str r1, [r0]


and wait for it to interrupt...

Code: Select all
   /* Address of GPU Pending 2 register */
   ldr r0, =0x2000B208
   
   /* Wait for the 48 SMI / VSync interrupt to occur */
LoopVSync$:
   ldr r1, [r0]
   tst r1, #0x00010000
   beq LoopVSync$


Hope this helps.
Posts: 45
Joined: Fri May 04, 2012 6:44 pm
by gertk » Tue Oct 30, 2012 6:26 am
Great ! Will try this tonight!
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by DrPinball » Tue Oct 30, 2012 11:54 am
Let me know how you get on with it!
Posts: 45
Joined: Fri May 04, 2012 6:44 pm
by gertk » Tue Oct 30, 2012 10:37 pm
It works ! Thanks!

Had to puzzle a bit to get both the uart interrupt and the 'new'SMI' interrupt working until I found out they were handed to the same handler :D
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by gertk » Tue Oct 30, 2012 11:46 pm
And got a decent speed now also, enabled the L1 cache and optimized the display routine a bit.
Progress!
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by gertk » Wed Oct 31, 2012 12:13 am
DrPinball wrote:Let me know how you get on with it!

After some testing it seems that the Vsync interrupt is occuring midscreen ?
(at least that is where there is visible tearing during motion)
Maybe because of double buffering of the GPU ? (or simply because my display routine is till too slow :o )
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by jackokring » Wed Oct 31, 2012 1:53 am
gertk wrote:I'm not sure if the display routine is the culprit or the Z80 emulation compiled by gcc is a lot slower than when using the mbed compiler. The emulator on the Pi is doing 4 to 5 frames per second...


If you've got a link to the Z80 specific (opcode decode, dispatch and evaluation C) files, I'd be happy to look at it for possible optimization.
Pi=B256R0USB CL4SD8GB Raspbian Stock. https://sites.google.com/site/rubikcompression/strictly-long https://dl.dropboxusercontent.com/u/1615413/Own%20Work/Leptronics.pdf https://groups.google.com/forum/#!topic/comp.compression/t22ct_BKi9w
User avatar
Posts: 784
Joined: Tue Jul 31, 2012 8:27 am
Location: London, UK
by ejames » Fri Nov 02, 2012 4:36 pm
I 100% agree with hermanhermitage, I had the same idea.

To that end I've created a repository on github for PiOS

My aim is to get a very barebones skeleton of an OS up and running in a similar vein to DexOS and the Baking Pi course. Rather than a specific OS I guess what the barebones community needs is a set of high quality handy routines for accessing things such as USB, a font manager, OpenGL and so on. We can then all get on with fun things like building an arcade game console or robots or toasters instead of everyone having to reinvent the wheel for these essential basics.

I myself have one of these and am planning to build a robot telescope around the Pi using the touchscreen for the user interface.

I guess the next step is for those who are interested to all gravitate to one place....I'd be happy for that to be PiOS.

I'll try to contact Craig Bamford (DexOS) and Alex Chadwick (Baking Pi) to see if there's anything they can contribute seeing as they have some things working already.

I would plan to make PiOS available under a similar Creative Commons license to the Baking Pi code.
Posts: 15
Joined: Thu Feb 02, 2012 1:19 pm
by ghans » Fri Nov 02, 2012 5:02 pm
AFAIK the Plan9 guys have totally new ("clean" ?) USB implementation ,
this might help.


ghans
• Don't like the board ? Missing features ? Change to the prosilver theme ! You can find it in your settings.
• Don't like to search the forum BEFORE posting 'cos it's useless ? Try googling : yoursearchtermshere site:raspberrypi.org
Posts: 4754
Joined: Mon Dec 12, 2011 8:30 pm
Location: Germany
by poglad » Tue Nov 06, 2012 1:47 pm
Wow this is superb, only just noticed it here. Don't worry about the keyboard line handling - a ZX81 keyboard membrane is a tenner off eBay! Even if you get it working via a USB keyboard, you should retain the possibility of connecting a real membrane as an option! :lol:

Do you get the nice load/save lines on the screen? For testing, RAND USR 777 in fast mode dives straight into the SAVE routine for an extended period. :D
User avatar
Posts: 102
Joined: Tue Jul 31, 2012 8:47 am
Location: Aberdeen, Scotland
by gertk » Tue Nov 06, 2012 5:39 pm
poglad wrote:Wow this is superb, only just noticed it here. Don't worry about the keyboard line handling - a ZX81 keyboard membrane is a tenner off eBay! Even if you get it working via a USB keyboard, you should retain the possibility of connecting a real membrane as an option! :lol:


Due to limited IO pins this might not be feasible but my first priority is to get SD card access and USB keyboard working. So far I have updated the screen display routine so speed is above standard ZX81 speed already (using 640x480 canvas in 16 bit).
On the mbed (my 'NXP81') I had just enough IO pins to handle a real ZX81 keyboard, a joystick interface (in fact an extra keyrow converted in software to ZXpand compatibility) SDcard and PS2 keyboard interface and the ADC/DAC pins are free for future audio in/out.

Do you get the nice load/save lines on the screen? For testing, RAND USR 777 in fast mode dives straight into the SAVE routine for an extended period.


Nope, since there is no FAST and SLOW in my emulator the lines are also not present, just a nice rocksteady HDMI (or CVBS) display :) BTW, loading and saving will be so fast there will be no lines visible (at least on the mbed it loads and saves in an instant: type LOAD "whatever.p", press NewLine and zap, program loaded..)
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by poglad » Tue Nov 06, 2012 9:23 pm
Ahhhh... at the risk of being pedantic... no no no! Emulating the electron beam timings is a big part of the challenge of the ZX81. It really shouldn't be much more work than what you have already, you "just" have to determine whether a signal (including vsync, hsync) is actually coming from the "ZX81" as you're scanning down your frame buffer... and to follow the same kind of behaviour a TV would when the signal suddenly returns with a vsync at an unexpected moment. i.e., the picture rolls for a few milliseconds until the TV catches up.

Seriously, it's really worth doing for authenticity, and might actually be necessary for certain clever software that does special screen modes based on timing. The thrill of a ZX81 with rock-solid display would soon dissipate... rather like a Speccy without attribute clash hehe! :lol:
User avatar
Posts: 102
Joined: Tue Jul 31, 2012 8:47 am
Location: Aberdeen, Scotland
by gertk » Tue Nov 06, 2012 10:41 pm
poglad wrote:Ahhhh... at the risk of being pedantic... no no no! Emulating the electron beam timings is a big part of the challenge of the ZX81. It really shouldn't be much more work than what you have already, you "just" have to determine whether a signal (including vsync, hsync) is actually coming from the "ZX81" as you're scanning down your frame buffer... and to follow the same kind of behaviour a TV would when the signal suddenly returns with a vsync at an unexpected moment. i.e., the picture rolls for a few milliseconds until the TV catches up.

Seriously, it's really worth doing for authenticity, and might actually be necessary for certain clever software that does special screen modes based on timing. The thrill of a ZX81 with rock-solid display would soon dissipate... rather like a Speccy without attribute clash hehe! :lol:


:D
Yes I have thought about this and have lots of documentation already on this and probably will implement it too but for now it is not my main priority.
I agree it is one of the neatest features of the ZX81 and it is absolutely necessary for most of the Hires Demos to run. I have implemented UDG already so for example HR-Galaxians runs fine.

An USB keyboard (or even membrane via GPIO) is also mandatory because you need the 'make' and 'break' events to properly mimic the keyboard matrix. With a serial console you only have 'make' events, the 'break' events are now simply timed which is not reliable.

I added a (s)printf function for debugging and it will also help to get the sub programs under the function keys working again as I have on the mbed ZX81 emu (there F1 displays a text version of the Basic manual, F2 pops up a disassembler, F3 a hexdumper and F4 shows the current Z80 registers and flags)
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by gertk » Sun Nov 11, 2012 10:14 pm
very_small_2012-11-11 23.41.07.jpg
very_small_2012-11-11 23.41.07.jpg (49.93 KiB) Viewed 2745 times

Could not resist...
I have made some progress in emulating the ULA chip, the screen is now 'built' with the original INT and NMI interrupts for the active and blank lines. Fast and slow modes are also working.
Alas none of the Hires programs are working, it still needs some more tweaking.
Now a horizontal line interrupt would be nice...
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by poglad » Mon Nov 12, 2012 1:57 pm
Goody!!! This is great stuff.

Concerning the shortage of GPIO pins for use with a membrane keyboard, I wouldn't worry much about that. As long as the keyboard is put through something like a MCP23017 chip, which is just a wiring job really, it will magically transform into an i2c device that requires only two pins. Err, so they say. :roll:

Now, if you can map GPIO access into the memory or port space of the ZX81, then we'll be able to write software to control the Gertboard etc. :P
User avatar
Posts: 102
Joined: Tue Jul 31, 2012 8:47 am
Location: Aberdeen, Scotland
by gertk » Mon Nov 12, 2012 6:33 pm
poglad wrote:Goody!!! This is great stuff.
Concerning the shortage of GPIO pins for use with a membrane keyboard, I wouldn't worry much about that. As long as the keyboard is put through something like a MCP23017 chip, which is just a wiring job really, it will magically transform into an i2c device that requires only two pins. Err, so they say. :roll:


Hmm, I know that chip in SPI form: the MCP23S17, did a graphic LCD display attachment with it on the mbed, even a YouTube clip is lingering around :) http://www.youtube.com/watch?v=Hi2m3tru ... i2m3truUfI

Now, if you can map GPIO access into the memory or port space of the ZX81, then we'll be able to write software to control the Gertboard etc. :P


That will be the easiest part, I can add whatever I want into the memory or IO map. For ZX81 Basic it would be easiest to put it into the memory map so you can access it with Peek and Poke
Posts: 47
Joined: Mon Aug 29, 2011 9:08 am
by poglad » Mon Nov 12, 2012 9:35 pm
That's true, although traditionally it was never done that way... I seem to recall always having to write little machine code things in a REM statement to do the OUT instruction! :lol: Whichever memory locations you choose, they won't be available for RAM any more (obviously). If you were cunning, you would map it to ports including 31, and 5 of the GPIO pins would "just happen" to provide a Kempston joystick interface hahaha...
User avatar
Posts: 102
Joined: Tue Jul 31, 2012 8:47 am
Location: Aberdeen, Scotland