Monday, September 19, 2011

Integration

Much recent development on the ZX Prism has been to integrate the video modes from the orignal (48K) Prism development into the new 256K one. This has thus far been pain free but of course there's nothing new to show! The only component I'd implemented in the original Prism which hasn't been integrated yet is the palette memory, and that's next on my list.

Remembering the issue with "offset" screen attributes in the original paletted solution, and having identified some other timing issues relating to the video output and interrupts, I'm rewriting the video creation module including making the clock resolution higher. This allows me to fit the palette lookups into the standard video read/store cycle. It should also mean a resolution of 512x384 will be possible.

The new video module will be written with the additional screen resolutions and colour decoding modes in mind (rather than them being retrofitted to Mike Stirling's video module).

Whilst designing the new video module, ideas for additional video modes have arisen, including an "overlay" mode where the shadow screen is used as a background for the main screen - any areas of the main screen which are colour 0 will allow the shadow screen to show through. This could be used, for instance, for games - where the sprites are animated on the main screen, and coloured backgrounds are drawn on the shadow screen. There'd still be attribute clash between the sprites, but not between the sprites and the background.  It's only 3 colours rather than two in each 8x8 attribute square, but it would provide a relatively easy way of sprucing up existing software.

Wednesday, September 7, 2011

A matter of contention

Once interrupts were fixed, I turned my attention to emulating the Spectrum's floating bus. Basically, I keep a copy of the last byte read by the video circuit. If the CPU reads an I/O address where the LSB is FF, I feed it a copy of that  last byte when the screen is being drawn, otherwise I send back 0xFF. At some point in the future, I'll alter this so that this is the response to ANY unused I/O address but it suffices for now.

The next thing to tackle was memory and IO contention. Whilst ZX Prism currently timeslices the bus between the video circuit and the CPU to avoid bus collisions, quite a lot of software uses precise timings (for screen efects etc).  After much messing around with alternatives, I bit the bullet and implemented IO and memory contention based on the 6C0001 ULA's circuit as described in detail in Chris Smith's ULA book. It didn't work. At all. In fact the screen erupted in a multicoloured mess.



Puzzled, I poked around and tried various things to the point of calculating propegation delays around the circuit, but to no avail. It was then I realised that I hadn't inverted the incoming clock signal. Hey presto. Prism initialised.



I didn't have much time for further testing at this point, but the couple of tests I did perform were encouraging although there's definitely a couple of things still need fixing:
  • Aquaplane - Split border effect is almost correct (it occurs just under 1 line early)
  • Fusetest - runs without crashing, but shows a contended frame length which is shorter than expected and most other tests show as failed
  • ULATEST3, Floatspy - both still crash
  • IR_contention - A very interesting effect here. This test shows four coloured boxes in the top and bottom border which should be parellel to each other. They are... however they are twice as long on ZXprism as they are on a real spectrum (or on the Spin emulator in 48k mode) - in fact the whole line wraps round on-screen. Looks like I need to take another look at the video and interrupt generation.




You will notice that I've implemented a 48K Spectrum contention solution on a machine which is compatible with the 128K Spectrum. I will be changing the contention so that it contends the appropriate memory pages in the future.

Sunday, September 4, 2011

Interrupts...

This last week has seen me working with interrupts of various types.

Firstly, the literal. Mike Stirling released a new version of FPGASpectrum during the week and I took some time from working on ZX Prism to check it out. I was impressed. Mike has very quickly added a number of new features

  • AY Soundchip core
  • IO Port 7FFD controlling RAM/ROM paging as on all 128K Spectrums
  • IO Port 1FFD controlling ROM and CP/M memory modes as on the +2A and +3
  • ZXMMC+ (allowing the Spectrum to access SD Cards and adding another 128K of RAM and 128K of ROM)
This left me in a quandry. I'd been going to add 128K support to ZX Prism as part of the memory expansion to 512K (or 1MB if I could get the DE1's DRAM working), and whilst I'd been going to add IDE support to ZXPrism (via a divIDE interface), the ZXMMC+ allows access to the SD Card slot which is already on-board.... So... do I use THIS as the new foundation for ZX Prism and start merging in the changes I'd made to Mike's original VHDL, or do I try to merge Mike's changes into ZX Prism? 

Either way, I had to rethink how I was going to do Prism's expanded memory (as ZXMMC support uses 256K of the DE1's SRAM)

I decided on the former - after all, I knew exactly what changes and additions I'd made for Prism. Memory-wise, the upper 256K of the SRAM is used by the ZXMMC+ implementation. The lower 256K of the SRAM will be switchable in 16x16K pages at 0xC000 (using the Pentagon 256 decoding of port 0x7FFD to switch it). I'll be using on-FPGA memory cells for the video ram (pages 5,7,D and F) due to the way the video subsystem will be reading it - this gives another 64K of the SRAM available for.. something.

So, much of my time recently has been spent on integrating my changes into Mike's new codebase. As I'm new to VHDL and FPGAs, this has been a learning experience as Mike has changed from using a schematic  top level to using a VHDL top level - therefore my progress is slower than it might have been otherwise. All good learning though.

As part of integrating the ZX Prism code, I decided to take a look at how the Spectrum's interrupt was being generated (aha, there's the other tie-in with the post's title). 

Some code on the Spectrum relies heavily on certain features of the Spectrum hardware:
  • accurate generation and duration of the Spectrum's video interrupt
  • accurate emulation of memory/IO contention (ZX Prism's bus is arbitrated by timeslicing so there's no need for contention in order for things to work, but it IS needed for Spectrum code to run at predictable speeds)
  • the Spectrum's floating bus

I'll be looking at all of these things (as I know Mike is,), but the easiest thing to look at was the video interrupt, which I coded to behave precisely as Chris Smith describes in the ULA book.  Once this was done, I tried running some of the software which wasn't working correctly:

  • ULATEST3 - still crashed
  • Aquaplane - border effect still starts too early on the screen
  • FUSETEST - no longer crashes

Tiny steps...

Tuesday, August 23, 2011

Paletted 256 colour mode

ZX Prism currently has 3 different screen modes. The first is, of course, the standard ZX Spectrum mode (256x192 pixels, 8 colours, 2 per 8x8 attribute square, 2 brightness levels - 1 only per 8x8 attribute square). The second is a 32 colour mode as pictured in a previous blog entry (256x192 pixels, 8 colours, 2 per 8x8 attribute square, 4 brightness levels, 1 per 8x8 square).

The third mode is the one which I've been working on recently and had success with last night. It's one of several proposed 256 colour modes. This one uses the attribute byte to determine the logical ink colour (0-255). The paper colour is determined by the ULA2 border colour stored in a latch at 0x4E3B.

Testing 256 colour mode (mode 72) - random palette

Testing 256 colour mode (mode 72) - random palette

Atic Atac loading in 256 colour mode with a randomised palette.
Note the effects of the timing issue on the Ultimate logo
The rainbow stripes don't work when there's only one paper colour!

(C) 1982 Sinclair Research in lime green. 
It had to be done.

There are a number of bugs/"features" with this mode:

  • Background colour is dictated by the ULA2 border colour. The ULA2 border is only active when the ULA border is set to black (BORDER 0). Careful manipulation of the ULA2 border colours during the screen refresh should be able to increase the number of colours on-screen. Other, similar effects can be achieved by switching screen mode at appropriate times during screen refresh.
  • It follows that setting the ULA border to a colour other than black means you can have a border that doesn't match the 'paper' colour. If the ULA border colour isn't matched in the 256 colour palette, then you have an extra colour on-screen (if anyone's counting).
  • A noise effect is notable on the colour whose palette entry is being updated due to lack of contention on the dual-port palette RAM. This could potentially be fixed, however it could also be exploited as a special effect. For now I'm leaving it alone.
  • The pixel colour can be selected from BASIC by manipulating ink, paper, bright and flash values. 
  • As can be seen from the pictures - there are timing issues caused by the palette lookup cycle (at least I think this is the cause). These will need to be fixed, however the display being created is stable, and the which is very encouraging. 
Having a single paper colour for the whole screen isn't particularly useful for detailed graphics. Other similar paletted modes are to be implemented which will be more useful:
  • 16 inks, 16 papers. Paletted. 2 colours in each 8x8 attribute square
  • 32 inks, 8 papers. Paletted. 2 colours in each 8x8 attribute square
  • 64 inks, 4 papers. Paletted. 2 colours in each 8x8 attribute square
  • 128 inks, 2 papers. Paletted. 2 colours in each 8x8 attribute square
  • 256 colours, Paletted. 2 colours in each 8x8 attribute square. 2 byte attributes.
  • The above modes, but with 8x1 pixel attributes.
  • ULAplus

Sunday, August 21, 2011

Clocks

One other major thing that has changed recently in ZX Prism is the master clock frequency.

Mike's original FPGA Spectrum source derives the CPU and video clocks from a 28MHz phase locked loop. The 14MHz video clock was derived from every odd tick (equalling four ticks for every eight of the master clock: 1,3,5 and 7) and the 3.5MHz CPU clock was derived from the first even tick of every eight (tick 0). The 7MHz CPU mode was derived from ticks 0 and 4.

Recently, to prepare for the more complex video modes and to allow faster CPU clock frequencies I doubled the master clock frequency to 56MHz. For now, I've adjusted the way the CPU and Video clocks are derived so they still run at 14Mhz and 3.5 or 7MHz.

The on-FPGA palette memory seems quite happy at these speeds, so all is looking good for the new screen modes.

The next thing to do is to increase the video clock to 28Mhz and adjust the read/store cycle for reading the data and attribute bytes. Some of the new screen modes need more data to be shifted around than the standard Spectrum mode. I'll be attempting to do the majority of the screen modes with the same contention patterns (at least when the CPU is running at 3.5Mhz) so that games with special screen effects (split borders etc) work. The chunky and planar screen modes will probably incur more contention - though the CPU speed can be increased to compensate of course.

Speaking of contention... I've still not had complete success with implementing it - however I am a lot closer now. The increase in master clock frequency and the redesign of the video decode/encode subsystem gives me a chance to change how the timing of everything fits together - including ensuring contention is correctly applied at faster CPU speeds to avoid the crashes that currently happen when the CPU is running at 14 or 28MHz. Time to get the pencils and paper out and start counting clock ticks...

Mode switching

Recently, I've been doing a number of tests of different attribute byte decoding schemes, but of course the ultimate goal has always been to be able to switch screen mode from basic or machine code. Today I made inroads into making the screen mode switchable. An 8 bit latch at 0x1E3B serves as the screen mode selector. 5 bits controls how the video data is decoded to determine pixel colour. The remaining 3 bits control the screen resolution: M4 M3 M2 M1 M0 R2 R1 R0

Currently I have 3 screen modes implemented:
  • 00000xxx - Normal Spectrum mode ( Fl Br P2 P1 P0 I2 I1 I0 )
  • 00001xxx - 32 colour mode (Br1 Br0 P2 P1 P0 I2 I1 I0)
  • 01010xxx - 256 colour mode, paletted (I7 I6 I5 I4 I3 I2 I1 I0), paper=border colour
(key: Fl = flash, Br=bright, Px=paper, Ix=ink)

In the 256 colour mode, the paper colour is determined by the 256 colour border colour stored in another 8 bit latch at 0x4E3B. The 256 colour border is available in all modes when the "normal" spectrum border is set to colour 0.

This is a paletted mode, and by default all colours are set to black. The palette is controlled as follows:

OUT 48699,colour number
OUT 65083,red level
OUT 65083,green level
OUT 65083,blue level

The colour to be redefined is stored in a counter at 0xBE3B. Then the red,green and blue levels for that colour are output to 0xFE3B. Each successive write to 0xFE3B goes to the next colour element - red, then green, then blue. After the blue level is written, the colour number increments and therefore a subsequent write to 0xFE3B will define the red level for the next colour and so on.

Initial tests of the paletted mode are encouraging. The colours are able to be redefined, however there are some interesting effects due to timings which will need to be ironed out.

Sunday, August 14, 2011

Progressing slowly....

This past weekend has seen a number of steps forward. The unpaletted 32 colour mode proof-of-concept code was expanded to allow the border to be one of 256 colours (bits 7..0 equating to 2 bits blue, 3 bits green, 3 bits red - BbGggRrr). This tested the ULAplus-style 8 bit palette.

The border is currently controlled by an OUT to an 8 bit latch and currently replaces the usual 3 bit border. Another latch has been implemented which selects the CPU speed and in the future will also reflect "machine type" (or at least which memory paging system to use). Setting and unsetting bits 0 and 1of this latch selects between the 4 CPU speeds implemented.
  • 00 - (default) 3.5MHz
  • 01 - 7Mhz
  • 10 - 14Mhz
  • 11 - 21Mhz
As at this point only 3.5MHz and 7Mhz modes work correctly. 14MHz doesn't work yet as the video ram is on the same data and address bus as "normal" (uncontended) RAM and memory contention isn't yet implemented. Likewise, 21MHz causes bus collisions (and some rather pretty crashes)

Speaking of implementing memory contention. At 3.5Mhz I want this to be as accurate to ZX Spectrum timings as possible.  My attempts thus far to implement ANY sort of delay when the CPU address space is within video RAM have been unsuccessful:

  • Machine seemed to run as usual. Could load from tape successfully. Aquaplane's border effect switches colour around 12 lines early - this is the same as without the contention circuit. Conclusion: contention enabling logic was incorrect.
  • Machine seemed to run as usual. Loading from tape was unsuccessful - pilot tones were detected, but data wasn't correctly decoded. Conclusion: CPU was being disabled for too many cycles.
  • Machine seemed to run as usual. Loading from tape was unsuccessful - pilot tones were not detected. Conclusion: CPU was being disabled for too many cycles.
  • Machine displayed garbage on screen and didn't initialise. Conclusion: as soon as contention was applied, the CPU was effectively halted (this was backed up by monitoring the address bus)
Additionally, I've confirmed that code using the R register fails consistently. Speedlock 1 works right up until the loading completes and then crashes. Most machine test suites (ulatest3, fusetest etc) fail spectacularly - the two aforementioned test suites crash in fact. 

I shall revisit memory contention later. For now, I can live with the fact that some software which relies on cycle-accurate memory contention (eg for border effects) will look odd. The crashes and apparently incorrect CPU behaviour is more of an issue, but again I can do little about it at the moment. The T80 code isn't well documented at all and I'm still learning the ropes with VHDL really. A little bird tells me that someone working on another "advanced Spectrum" style project has done some bugfixes to command timing and flag behaviour, so I'm hoping they'll share them with other T80 users in the future.

Finally, I talked to Andrew Owen regarding reserving a block of IO addresses in the ZXI standard. This means that the ZX Prism's IO addressing won't clash with any other ZXI certified device, for example Spectranet and ULAplus (though of course ZX Prism will be providing ULAplus functionality at its usual ports anyway). This is especially important if I intend to add an edge connector to ZX Prism so that it can use existing ZX Spectrum peripherals like divIDE etc, or should I build a plug-in for a standard ZX Spectrum which provides some or all of the ZX Prism's extended functionality.

The range I have been allocated is xE3Bh which gives me 16 IO addresses which should be plenty. Currently I've earmarked:
  • 0E3Bh - ZXPrism hardware control (CPU speed, memory paging method select, etc)
  • 1E3Bh - ZXPrism screen resolution select/attribute decode method select
  • 4E3Bh - Border colour
  • 6E3Bh - Memory Page at 8000h
  • 7E3bh - Memory Page at C000h
  • BE3Bh - (write only) ULA2 palette (colour select)
  • FE3Bh - (write only) ULA2 palette (R/G/B data)
Currently I'm planning using 16K memory pages (per Spectrum 128/Scorpion/Pentagon). This may change to 8K pages (Timex/Spectrum SE/ZX81) or be switchable, however I don't want the memory bank switching to become too complicated.  

Tuesday, August 9, 2011

32 colours!

Today I started rewriting Mike's video code. As a test, I disabled FLASH and used bit 7 of the attribute byte to make a 2-bit BRIGHT: 4 different brightness levels of 7 different colours plus 4 identical shades of black... So technically 29 colours.


Obviously I made the non-bright, non-flash colour level a little too dark, but as a test it sufficed admirably.

Yesterday out of interest I ran a number of test suites with interesting results. ULAtest3 completely crashed - reset the machine. Fusetest did a few tests and then crashed. Z80test failed on all MEMPTR tests and most of the register tests involving the R flag. Taking another look at Mike's VHDL I noticed he's using the T80se core - and it states that it doesn't match true Z80 timings. It's also an older version. I'll download the latest version of the normal T80 core and see if I can replace it.

Finally, here's a picture of Aquaplane showing the broken border effect due to issues with the T80se core having different timings and the lack of bus contention. 


Sunday, August 7, 2011

More testing

Today I looked at some other open-source FPGA based Spectrum compatibles but had very limited success. Nonetheless, there were some interesting ideas in the implementations which might be drawn on later.

In short, I'll be pulling some ideas (and perhaps using a bit of code) from ZXGate and from the 128 Spectrum implementation which is part of Alex Freed's FPGApple - but the basic foundation of ZX Prism will be the T80 open core Z80, and some of Mike Stirling's FPGA Spectrum code.

Further testing of Mike's Spectrum, with the likes of Aqua Plane and reading some of the comments in his VHDL code confirmed my suspicions - as the implementation handles bus arbitration differently, there are speed differences between it and a real Spectrum when the CPU wants to use the video RAM at the same time as the video circuit.

So my first task will be to make some alterations to make a nice sturdy "foundation" for all the bolt-ons mentioned yesterday to bolt onto:

  • To use the DE1's FLASH memory for its ROM
  • To use the DE1's SDRAM instead of the SRAM
  • To more accurately emulate the Spectrum's floating bus and contended RAM

Saturday, August 6, 2011

We have lift-off

Today I trialled Mike Stirling's open source FPGA Spectrum on the DE1. I successfully loaded Atic Atac from tape with no problems but Beach Head failed - possibly because of a loading error or possibly due to Speedlock 1 being quite... finicky.

The spectrum screen is slightly misplaced on the display - there's a blank area before the border starts on the left. A few tweaks to the clock code didn't help this but I didn't spend much time on it - at the moment I'm looking at a number of open source FPGA Spectrum solutions to select which one I wish to use as a basis for the Prism - or I might use bits and bobs from different solutions. Basically I just need a basic framework on which to add my mods/extensions.

Currently, using Mike's code, the Prism is as follows:


  • 48K Spectrum compatible
  • Tape Input
  • PS/2 keyboard interface
  • Switchable VGA/RGB output

When deciding which code framework to start from I'll also be looking at ZXGate (which does Spectrum, ZX81 and Jupiter Ace) and another which is an offshoot from an FPGA Apple machine and emulates a Spectrum 128. All look to have their benifits (ZXGate has the '81 support, the other has 128 memory paging etc and Mike's was written on the DE1 hardware which I'm using for Prism)

Planned mods/extensions:

  • Expanded memory - probably 1024K 
  • 64K video RAM
  • Pentagon 1024/Spectrum 128/+3 CP/M compatible memory paging 
  • 8K paging mode (towards ZX81/Timex/Spectrum SE compatibility) will also help when using some expanded screen modes
  • ULAplus compatibility
  • 256x192, 256x384, 512x192 and 512x384 screen resolutions
  • 8x8 and 8x1 screen attributes (8 bit attributes - either ULA or ULAplus)
  • 8x8 screen attributes (16 bit attributes - 256 colours, paletted)
  • 256x192 "chunky" 256 colour mode - 1 byte per pixel
  • 256x192 16 colour "planar" mode (paletted/RGBI)
  • ZX81 compatible text mode
  • possibly other text modes
  • Look at hardware flicker-free multitech/gigascreen modes
  • Built in magic button (multiface-esque)
  • Expanded sound - "beeper", AY ACB/ABC stereo and SID
  • Support for adding a real SID and/or AY
  • DivIDE
  • +3 disk interface
  • "fast" modes - CPU speeds selectable 3.5, 7, 14, 28 MHz, possibly faster
  • Kempston/AGP and Sinclair joystick interfaces on break-out board
  • K-Mouse interface on break-out board