spacer

XGS-FrameBuffer

I’ve been coding a basic line buffer renderer for the XGS, I say basic because firstly its black and white only (well black and a fixed colour) and secondly its still in need of a good optimisation.

The current code takes up just under one page (<512 words), however with a lot of spare cycles there's the oppertunity to reduce the code size whilst still meeting the tight timing criteria. The largest chunk of the 512 words is taken up by the numerous uses of the DELAY macro in generating the HSYNC delays, shifting this to a subrouting would make quite a difference.

The buffer itself handles 200 pixels with 4 pixel padding either side, giving a horizontal resolution of 200 active pixels and 8 overscan. Vertically it uses 208 active lines with 48/52 lines for top/bottom overscan and 4 vsync lines totalling 312 vertical lines. Although I'm considering reducing the overscan lines and increasing vsync to 10 lines to provide a greater number of spare cycles in one chunk for gameplay logic.

The line buffer uses 25 bytes of internal RAM (banks 1 & 2) for storage with each byte holding 8 pixels (thus the reason for single colour only support atm)

The line buffer is populated during each of the hsync periods utilising the spare cycles. During the active line period the code generates the required tv signal to output each pixel of the line buffer with only 20 cycles (250ns) per pixel available

Currently the biggest question is whether 900 cycles will be enough time to generate 200 pixels worth of data and cache it to the line buffer banks. With a player sprite, enemy sprites and missiles in the mix the cycle count could be quite tight.

The main rendering loop still has quite a few cycles to spare, around 12 per pixel, however using these will mean tightly coupling the line buffer generation with the rendering, which is something I would like to avoid.

Although not in place yet, the plan is the for game logic to run during vsync, which assuming we use 10 lines would provide just over 50,000 cycles for game logic. A further 420k cycles are available during the overscan generation which means there's plenty of room for gameplay logic and music.

Part way through building the line buffer I attempted to generate a pal signal with the colour GREEN for an on pixel and BLACK for an off pixel. However, my TV would not recognise the signal as PAL with colour output when using the NTSC setting only.

As the following forum thread describes, PAL has a few extra requirements to NTSC.


  • 1 - Colour burst on alternative lines must be phase shifted +- 45 degrees
  • 2 - Each colour output must be phase shifted by 180 degrees on alternative lines

With James’ help and a fair amount of time reading the PAL specs and XGS specs, the TV finally picked up on this been a PAL signal and displayed bars in all their colour :)

XGS PAL Signal Generation

Next step will be finalising the hsync callback code to render a player sprite under joystick control.

At a later date I’ll probably look into increasing the size of the line buffer to 100 bytes which would allow 200 pixels at a bit depth of 4. Then up’in the sprites from been an 8bit x 8bit block to support 4 bits of colour information per pixel. Using a palette this would allow for colours 16 colours.

A larger bit depth is plausible especially if its moved out to the external SRAM, however doing so may require some creative thinking in order to meet the timing requirements of 20 cycles per pixel.

Once the code is more functional and rendering a few sprites I’ll get it uploaded, perhaps with a pdf explaining everything for any XGS owners that are interested :)

XGameStation

 

Black and White

No not the game Black and White (although it was a good game), I’m talking black and white TV, the next evolution of my console. I’d give it a name but it’s currently too close (almost identical ;) ) to the Pico to warrant it. Besides, choosing a name can be a difficult business, I’ll probably just not give it a seconds thought and pick anything, how about the “me”, the “you”, the “them”, the “we”… Wii thats the ticket. Wait what do you mean its already taken? Yes I know the joke has passed, but I couldn’t resist. Besides, I’m quite looking forward to it :)

I spent the better part of last weekend reading up on nodal analysis to be able to calculate the voltage at each junction of the R-2R ladder that I’ve added. The calculations themselves are simple, just an application of Ohms law. Simplifying the network however took most of the time, at least until the method finally clicked.

The Pico uses an R-2R ladder to convert the digital signal of the SX28 into an analogue signal ready for sending to a TV. Four pins on the SX28 allow 16 different voltages to be transmitted to the TV. The voltage levels are interpreted as intensity, however since the signal the TV uses 0.0v to sync on and 0.3v as black, that leaves around 10 voltage levels to play with.

Pico b&w graphics capable

Since the previous blog entry, I’ve reshuffled the layout with the power regulator on its own in the top left of the image. Partially cut off is the main power switch (currently taped down :P).

Looking at the main part of the image to the right of the SX28 you can see the R-2R resistor network used to convert the 4 bit digital signal into an analogue voltage which is adjusted to a 0-1.4v range via the bottom red potentiometer. Above the SX28 is the main external oscillator socket, the 80MHz oscillator is currently in the XGS. Just to the right of this, taped to the breadboard is a switch to select between the external oscillator and the 4 pin SX-Key header.

The hardware above is still almost identical to the Pico, however it won’t remain like this for long. The first divergance is probably going to come with the addition of joystick hardware. The Pico only supports a single joystick which is connected directly to the SX28. I’d like to have two ports (pong is two player afterall :P) so will be adding a serial interface for the joysticks.

The second area is either going to be interfacing with an SRAM chip or adding extra graphics hardware to take some pressure off of the SX28. I’m not sure which way to go with that yet, nor how problematic the pin count may be

To test the new hardware I created a quick test program that outputs a white bar at the top and bottom of the screen. The code used for signal generation is the “GID j - pixel in a day” code with the colour burst generation stripped out. Nothing fancy, but at least it’s working :)

XGameStation

 

We have a pulse

Continuing my adventures with the XGS I decided to make use of the larger breadboard bought the other week from maplins (along with a nice pre cut set of jumper leads).

My long term plan is to build a simple games console capable of loading games from an external flash rom (possibly cartridge based on simply onboard via switching to access a handful of pre-loaded games). This is a lot more work than it sounds since the SX range of chips can only execute instructions from their internal rom, 2K on the SX28 and 4K on the SX52. There are ways around this which I’ll cover at a later date.

There are a lot of hurdles between now and the simple console I’m picturing, so the first versions of the console will be limited to 2K of ROM and 144 bytes of RAM, basically the onboard rom/ram for the SX28. The SX28 (parallax micro-processor) is going to be the heart of my games console. The reason, because thats what the XGS used which means I have a boat load of reference docs, manuals and papers about it plus a local supplier and I’m already slightly familiar with SX assembly. Also, the SX28 is available in a DIL package which makes prototyping much simpler than the surface mount versions of the SX48 and SX52 (although I’ve a few of those ready for a future project :)

So the plan currently is to start very simple, and progressivly add more and more “features” to the console such as graphics/sounds/external flash rom & sram/joystick port etc If you’ve read the XGS ebook then you’ll probably notice many similarities to the PICO and XGS which are been used as a base reference, however I plan to expand the feature set of the PICO much further. For example with the addition of graphics and sound hardware. How far this can be taken with just the SX28 and the limited output pins, I’m not sure. At the expensive of speed I can probably serialise a number of the systems although worst case scenario will be stepping the design up to use the SX48. Thats the rough plan anyway, I’m sure it will change as I learn more.

Step one was getting a power supply up and running, actually very easy to do, a 7805 regulator did all the hard work plus theres quite a good section on power supply regulation in the XGS ebook :) I’m still not 100% certain on how the capacitors reduce the ripple in the DC supply, well I understand the concept but don’t quite understand the calculations enough to work out which frequencys are getting through and which are filtered. Something to work on in the future.

Anyhow, enough reading, heres a picture of a very basic SX28 project. In the top right of the picture can be seen the 7805 voltage regulator that takes a 9V DC supply and produces a 5V supply, along with the smoothing and noise filtering capacitors to clean up the 5V output.

SX28v0.1

For a breakdown of the circuit as well as the source code Read the rest of this entry »

 

GID j - Mission Accomplished

Having only had a few hours Sunday night to work on the last part of the code I wasn’t expecting to actually reach my goal of a pixel on the screen. In the end though, I managed to get a square block drawn in the center of the screen synced well enough to show flicker free on both my TV and Digital TV card in the PC.

The actual TV picture is a nice vibrant yellow, the screen capture doesn’t do it justice looking a little washed out. Oh, that reminds me, the colour burst wasn’t that hard afterall, just a case of making sure the colour is set in the upper 4 bits and the luma in the lower 4 :)

big pixel

Adding in the VSync and overscan code wasn’t that difficult, the hard part was counting all the clock cycles to make sure they met the timing requirements. In fact the most trouble was with the comparison loop where I check whether the scanline is within the block and needs to be drawn in colour. This results in 3 possible code paths all of which had to have exactly the same number of cycles before reaching the final DEALY(174-3) instruction. A little fudging goes a long way though :)

The theme for this GID was “Extreme Forces” well the forces exerted on my TV by all the badly formed signals I sent throughout Saturday were pretty extreme, does that count?

For those that care the source code is rar’d up and available for download. Although it works fine on my TV that doesn’t mean the code is correct so I’d love to hear back from any of the more experienced XGS users if you can see any obvious flaws. The final code weighed in at roughly 374 bytes (don’t quote me on that ;) ) After looking at a few other peoples delay macros I can see a saving of several bytes there alone, so I’m sure this code can be optimised significantly, maybe another day :)

Check out the rest of this entry if you want to see the final code

Read the rest of this entry »

 

GID j - signal generation

Having nailed the delay code I’ve spent most of the evening reading up on the SX52 memory architecture and the PAL timing signal. To start with I’ve created the signal needed for each scanline (see previous blog with timing diagram)

The first attempt didn’t go too well

Out of sync

It was only a few minutes though before I realise my timing was out by a few clock cycles. The reason? Well in order to generate say the SYNC pulse 0.0V on RE port for 4.7µs we need to delay for 4.7µs*1000/12.5ns = 376 clock cycles, so I did the following

[ASM]
mov RE, VID_SYNC
DELAY(376)
[/ASM]

The problem though is that really we’ve taken up 378 clock cycles and thus the code is executing for 25ns longer than we need it to. Couple this with all the other mov/delay statements for the other parts of the signal and we end up many cycles out of sync. The solution is simple, a mov takes 1 cycle or in the case of a compound mov (which this is) 2 cycles, so we just reduce the delay by 2 cycles to give

[ASM]
mov RE, VID_SYNC ; 2
DELAY(376-2) ; 376-2
[/ASM]

The result is a lot more promising, using VID_WHITE (1.0v) for the output port RE gives us a nice white screen, however we’re not finished yet, since there is not handling of the vertical sync yet.

Out of sync

So thats as far as I managed to get by the end of Saturday. I expected to have a good few hours sunday to work on getting the vsync sorted and plotting a specific pixel, but plans change. If I’m lucky I’ll squeeze in a few more hours tonight and hopefully finish things off.

 

GID j - Delay Debugging

GID j posts - first entry

As mentioned in the last blog entry, timing is cricical down to the cycle. In order to make sure all branches of code execute in the exact same amount of time I’ve created a delay macro. This isn’t an optimal method, I’m sure there are ways to reduce the number of bytes this uses however it does the job.. at least it does after a little debugging.

After coding up the above I programmed it into the SX52 and put the SXkey into debug mode which allows you to single step the processor one instruction at a time and view the programs memory/registers and flags. Using various delays of 1, 7, 10, 14 etc I noticed the NOP repeat was only generating a single nop rather than the expected number, this turned out to be because missed the ending ENDR directive

[ASM]
;
; DELAY for a specified number of clock cycles
; EXPECTS:
; “counter” 1 byte variable defined
DELAY MACRO clocks
; eat up clock cycles 10 at a time
IF ( (clocks / 10) > 0)
mov counter, #(clocks / 10) ; 2
:loop
jmp $ + 1 ; 3 jmp to next instruction
jmp $ + 1 ; 3 jmp to next instruction
djnz counter, :loop ; 2/4 (4 if <> zero)
; 10 cycles per loop, 8 for last loop
ENDIF

; handle remaining delay 1-9 using nops
IF ( (clocks // 10) > 0)
REPT (clocks // 10)
NOP ; 1
ENDR
ENDIF
ENDM
[/ASM]

The following screenshot (click for a larger view) shows the debugger running the DELAY(14) code and circled in red the lone NOP instruction. A simple mistake putting an extra slash but one which would if not caught render the video output useless. Glad I caught it early, otherwise I might have wasted hours debugging my video code.

delay debug

With the delay loop out of the way, its time to final make a start on generating accurate h/v signals. Hopefully by the end of tonight :)

 

GID j - Attempt 1 snow

GID j posts - first entry

Satuday 2pm and I’m a little closer to understanding how to plot a pixel, although only a little. The first attempt to generate a video signal resulted in, well see for yourself, detune a tv channel and look at the white snow, thats pretty close to what I’m looking at right now :)

The reason been, I’ve not setup any kind of timing for generating the video signal yet but I know that at least I’m outputting to the correct port to generate “a” signal. After a little digging through the XGS docs I’ve got the information on the PAL signal specs, the main bits of interest are:

  • Front Porch 1.5µs
  • Active Video 53.1µs
  • Sync 0V
  • Black 0.3V
  • White 1.0V

Based on this we can calculate the number of pixels a PAL tv can cope with (@5.5Mhz), we can change the signal at a rate of 1/5.5Mhz = 182ns which gives us 53.1µs / 182ns = 292 pixels per scanline (best case; although I think my tv will do 720 due to extra bandwidth, but we’ll go for a conservative value)

So in order to get a pixel (assuming no colour) on the screen I need to generate a video signal to display 312 scanlines each comprised of at most 292 pixels. Heres the full scanline signal needed for a PAL system. (I’m ignoring colour burst for now; image obtained from Haagans website)

Pal Sync signal

Once the horizontal signal is up and running the vertical signal should be a snap, its nothing more than another timing signal, so we’ll be sending a H Sync signal for each line followed by 4-10 lines of vsync. I’m keeping this simple and going for 274 lines at 50Hz (50 frames per second) with 16 blank lines top/bottom to account for tv variations and the 6 lines of vsync giving a total of 312 lines.

The key to this is the timing, with the SX52 processor that the XGS uses running at 80Mhz, 1 clock cycle = 12.5ns we need to ensure that the number of cycles used to generate the signal matches the above timing diagram.

There is a whole lot more to the signal generation than the overview above, if you’re really interested in the details either get the XGS and read the book (which in addition covers designing and building the actual video hardware) or google it.

So the plan for the larger part of today is to get a suitable delay macro up and running and outputting the appropriate voltages to generate a stable H/V signal. Initially using a fixed value for each pixel (we’ll get to plotting a single specific pixel later.. for now its a screen fill) Fingers crossed that is.

 

GID j - Black Pixels

Its that time of the month again, we’re now on GID j, for a change I thought I’d code something for the XGS. I sense this GID is going to be rather painful just setting things up ready for tomorrows start brought problems.

Lesson1: When routing the video/audio output through your digital tv card and you only get black and white check the Crystal. I’d forgot that the last time I used the XGS I’d hooked it up to my TV which supports PAL or NTSC and had been playing around with some of the NTSC only demos. I’d left the 3.57Mhz crystal in the XGS rather than the 4.43Mhz crystal needed for PAL output.

Lesson2: Prepare for things to only get worse from here on in. This little voice keeps telling me this is a bad idea. Trying to learn the details of programming a chip such as the SX52 and assosiated hardware is bad enough, but considering how rusty my asm skills are we’re in for a bumpy ride.

The chances of a successful GID appear to be slim to say the least, so I’m lowering my expectation (and I mean reeeealy lowering) and instead doing a PID; pixel in a day (if you hadn’t already guessed ). In other words, if I manage to get a pixel up on the screen within the time constraints of this GID I’ll be happy, anything beyond that is a bonus. On a good note I’ve already written code to handle interfacing with the joystick port (see previous blog) so if we can get a pixel up, maybe we can get it moving, perhaps even a several pixels ;)

Hey with 4k of direct memory who knows we may even get as far as displaying a sprite, maybe two but lets not get too carried away.

Anyhow the XGS is rigged up with video/audio routed through my pc to make for easier screen grabs (erm that is assuming we get as far as displaying anything, otherwise you’re in for some code dumps instead ;) ) so, for what remains of Friday night and a few hours of Saturday morning I’m going to hit the SX Programming manuals and read over the XGS hardware specs.

I think this first calls for a fresh cuppa.

 

Transistor Logic

Another day, another circuit, this one is a little more complex than the LED/Resistor circuit I made the other week. Having read about transistors I decided to design and build a NAND gate. The final circuit is very similar to the one discussed in the XGS ebook (below is the original circuit schematic from the very same ebook - which I highly recommend; a print version will be out soon as well :) )

NAND Gate Schematic

Aside from been a little blury the photo below shows my version of the NAND gate circuit built from two transistors, 3 resistors, two switches and an LED. The hardest part was finding a suitable 5V regulated power supply. I really need to buy a variable supply.

NAND Gate built

The far right of the image is where the +5V power is sourced, the far left is used as GND. The LED is connected to the +5V line via a resistor which results in the LED been lit by default. At the bottom right you should be able to make out the two switches, these connect the +5V supply to the base node of the two transistors (via one of the two 10Kohm resistors). Thus the switches control the input for the two transistors 1 or 0.

The collector of the first transistor is connected to the same resistor as the LED, with the emitter of this transistor feeding the collector of the second transistor. Finally the emitter of the second transistor is connected to GND.

The result of this is that when both switches are closed, the base of each transistor receives a sufficient voltage to start conducting from collector1 to emitter1 which feeds collector2 to emitter2 and finally running to GND. This gives us a working NAND gate. A 1 & 1 signal will result in a 0 i.e the LED will be off since both transistors are conducting to ground. Any other combination will result in a 1 as one (or both) transistor does not conduct, so we get a flow through the LED.

To most this probably isn’t the slightest bit impressive, its hard to appreciate the amount of background knowledge needed in order to understand how and why even simple circuit works, as well as analyse it; until you have done it yourself. So although it isn’t much to look at, I’m please with myself none the less :)

One lesson to take away from this is that it’s only once you begin to understand the basics that you start to finally realise how much more there is yet to learn. BTW I managed to get the joystick position to control the state of the LED that I mentioned in my previous XGS blog entry.

 

Every project needs blinking LEDs

Although I’m slowly working my way through the Design your own console ebook, theres a lot to learn, so I took a bit of a break last night and took a more hands on approach.

I built a very simple LED circuit and connected it to the XGS via the expansion port. That was the easy part, I then spent the next hour or two reading about the SX52 in order to program it to blink the LED on and off. It might not sound much, but considering I know very little about electronics and have never programmed the SX52 before, I’m pretty chuffed. In fact I’d rate the blinking LED achievment along the same lines as seeing your first triangle rendered via openGL, it doesn’t appear to do much but there was a lot of background work involved in getting that far :)

The XGS includes a lot of source code for a number of different hardware and software projects which I’m going to work through, although I prefer to try my own methods from scratch first. That way I can see just how far I can get from my own knowledge before getting stuck and having to refer to the working examples for hints/help.

So with that said, tonights challenge is to get the Joystick to light up an LED when you moved it in a specific direction. The circuit is about as simple as it gets, an LED, a resistor and a logic gate. Now I just need to find out how to talk to the joystick via the SX52.

Once I’ve built a more interesting circuit I’ll post up some screenshots. Although until I learn more about the overall hardware in the XGS the screenshots won’t be all that impressive :P

 
 
© 2005-2007 Gary Preston
Figment Games is hosted by DreamHost
Entries (RSS) and Comments (RSS).