Last visit was: Wed Dec 01, 2021 6:01 pm
It is currently Wed Dec 01, 2021 6:01 pm



 [ 70 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
 Sprite / Cursor Controllers 
Author Message

Joined: Fri May 08, 2015 6:22 pm
Posts: 61
robfinch wrote:
Another problem is the screen goes black during the sprite demo. There's no code to do that. But the screen bitmap address register is located right after the sprite control registers for the last sprite. I'm wondering if somehow the bitmap address is changing. -> so a routine that fills all the memory with color bands at startup might help indicate if this is true.

Are these separate register banks each with their own chip-select or equivalent, a timing issue here could result in the possible overlap effects your seeing.
What about an off by one issue updating the sprite control registers, overflowing onto the bitmap address register?

Quote:
Added clock enable control to the ram to reduce power consumption, previously the ram was enabled all the time for bootstrapping simplicity. On the display side the ram isn’t clocked during the vertical blanking interval. On the update side the ram clock is enabled only if an access is going to take place. If the machines sitting in the idle state no ram clocking takes place.

Sounds like something with the potential for timing issues to creep in, can it be disabled while hunting down other bugs in the system?


Sat Dec 09, 2017 3:01 pm

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
Quote:
Are these separate register banks each with their own chip-select or equivalent, a timing issue here could result in the possible overlap effects your seeing.
What about an off by one issue updating the sprite control registers, overflowing onto the bitmap address register?
There's just a single circuit select that selects a 2kB block. Registers are organized as a giant casex statement. There's a register shadow ram that also gets update so register values can be read back without muxing all the regs. There's hundreds of regs.
I would say it looks like an off by one error in software but I can't see how it could be. Here's part of the source to BouncingBalls. The test at .0007 is what loops through the register set. $200 to $3FE are the sprite control regs. $400 is the bitmap address register.
Code:
;
; Move balls around   
; Moves sprites 1-31 around on the screen (sprite 0 is the BIOS cursor)
;
; a0 = pointer to AV controller's register set
; a2 = pointer to sprite movement dx table
; a3 = pointer to sprite movement dy table
;
.0010:   
      move.w   #$210,d2         ; offset of sprite #1 regsiter
.0008:
      move.w   (a2,d2.w),d3      ; get dx
      add.w   d3,4(a0,d2.w)      ; add to hpos
      move.w   (a3,d2.w),d3      ; get dy
      add.w   d3,6(a0,d2.w)      ; add to vpos
      cmp.w   #BMP_WIDTH,4(a0,d2.w)   ; X hit limit ?
      blo.s     .0004
      neg.w   (a2,d2.w)         ; flip dx
.0004:
      cmp.w   #0,4(a0,d2.w)      ; X hit limit ?
      bhs.s     .0005
      neg.w   (a2,d2.w)         ; flip dx
.0005:
      cmp.w   #BMP_HEIGHT,6(a0,d2.w)   ; Y hit limit ?
      blo.s           .0006
      neg.w   (a3,d2.w)         ; flip dy
.0006:
      cmp.w   #0,6(a0,d2.w)      ; Y hit limit ?
      bhs.s           .0007
      neg.w   (a3,d2.w)         ; flip dy
.0007:
      add.w   #$10,d2            ; advance to next sprite register set
      cmp.w   #$400,d2         ; is end of register set hit ?
      bne.s     .0008   
      ; delay a bit to allow display to persist
      move.l   #80000,d3
.0009:
      sub.l   #1,d3
      bne.s    .0009
      bsr      KeybdGetCharNoWait   ; look for keypress to end
      tst.b   d1               ; d1 = -1 if no key
      bmi.s   .0010
      movem.l   (a7)+,d1/d2/d3/a0/a1/a6   ; restore regs
      rts

_________________
Robert Finch http://www.finitron.ca


Sat Dec 09, 2017 6:10 pm WWW

Joined: Fri May 08, 2015 6:22 pm
Posts: 61
Would a blt.s be better than the bne.s in .0007?
Currently, if d2 were to get messed up by a bug, the loop won't be exited.

Does changing the casex to a casez have any effect?
Based on page 9 of the following pdf.
http://www.sunburst-design.com/papers/C ... smatch.pdf


Sat Dec 09, 2017 8:41 pm

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
Yea, the blt.s would be better.

I changed the casex to a casez. Learned something new (not to use casex).

I finally read through the timing summary report and tons of timing errors on the path through the cpu, mmu and ddr ram controller. No timing errors in the AV controller core. It's amazing the system worked at all, but I think because it's a asynchronous bus with a transfer acknowledge signal that helped a lot. Anyway I re-wrote the mmu to register signals so now it takes another clock cycle for bus transfers, but it's a faster clock cycle. I also lowered the cpu clock rate to 16MHz from 40 MHz. I noticed a timing violation on 30ns half clock period. So the clock period needed to be >60ns. I may switch processing cores. TG68 is a great core but it's not particularly fast.

_________________
Robert Finch http://www.finitron.ca


Sun Dec 10, 2017 3:03 am WWW

Joined: Fri May 08, 2015 6:22 pm
Posts: 61
robfinch wrote:
Yea, the blt.s would be better.

I changed the casex to a casez. Learned something new (not to use casex).

There are more papers by Don Mills on his website, though most/all of them are mirrored on Cliff Cummings' website which is where the previously posted link came from.
Both sites are worth a look if they're not already on your radar.
http://www.sunburst-design.com/papers/
http://www.lcdm-eng.com/html/papers.html
Quote:

I finally read through the timing summary report and tons of timing errors on the path through the cpu, mmu and ddr ram controller. No timing errors in the AV controller core. It's amazing the system worked at all, but I think because it's a asynchronous bus with a transfer acknowledge signal that helped a lot. Anyway I re-wrote the mmu to register signals so now it takes another clock cycle for bus transfers, but it's a faster clock cycle. I also lowered the cpu clock rate to 16MHz from 40 MHz. I noticed a timing violation on 30ns half clock period. So the clock period needed to be >60ns. I may switch processing cores. TG68 is a great core but it's not particularly fast.

In my own little video chip project, I found that as I added more chipset registers to the list and the mux chain used for selection grew, the fMax of the CPU core dropped significantly. Have you seen a similar effect in your current design?
One interesting solution I've seen for dealing with a large number of chipset registers is the dedicated fastio bus used between the gs4510 CPU core and the VICIV video core of the mega65 project.
It's VHDL but is quite easy to follow with fairly sensible signal naming.

GS4510: https://github.com/MEGA65/mega65-core/blob/master/src/vhdl/gs4510.vhdl
VICIV: https://github.com/MEGA65/mega65-core/blob/master/src/vhdl/viciv.vhdl


As for switching to a faster core, is there a fast open source 68K core, or are you thinking of switching to a different CPU architecture?


Sun Dec 10, 2017 7:51 am

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
Quote:
In my own little video chip project, I found that as I added more chipset registers to the list and the mux chain used for selection grew, the fMax of the CPU core dropped significantly. Have you seen a similar effect in your current design?
Yes I have found that with mux chains. So I don't use them if possible.
In order to write a register set there should not be a mux chain. Reading the register set is different, the data outputs need to be muxed. I've found that the tools seem to generate much faster hardware by using a case (or casez) statement where possible rather than a series of if/elsif statements. If/elsif will generate a priority chain, cascaded logic, unless the tools can optimize it away. A case statement just generates a bunch of enables, parallel logic.

Quote:
As for switching to a faster core, is there a fast open source 68K core, or are you thinking of switching to a different CPU architecture?
I was thinking of maybe switching to RiSC-V. Or a custom solution with a wider bus.

_________________
Robert Finch http://www.finitron.ca


Sun Dec 10, 2017 2:41 pm WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
The screen going black when the BouncingBalls sprite demo runs has me mystified. I've tried several experiments with no luck yet. The only thing I can think of is that there is a giant sprite masking out the screen. It could be the case that the giant sprite is blocking the screen from view while allowing other sprites to appear in front. It would have to be the InBox logic that's screwy somehow.
Code:
// final output registration

always @(posedge clk)
   casez({blank4,border4,any_cursor_on4})
   3'b1??:      rgb <= 15'h0000;
   3'b01?:      rgb <= borderColor;
   3'b001:      rgb <= ((zb_i4 < cursor_z4) ? rgb_i4 : flashOut);
   3'b000:      rgb <= rgb_i4;
   endcase
always @(posedge clk)
    blank_o <= blank4;

In the output registration the only option that could be failing is 3'b001. If one of the other cases were failing then there would be no sprites appearing on screen. And they do appear.
My next test modifies the alpha blending so that there isn't any. It could be the color blending is bad.

_________________
Robert Finch http://www.finitron.ca


Mon Dec 11, 2017 3:23 am WWW

Joined: Fri May 08, 2015 6:22 pm
Posts: 61
As a quick test I'd be tempted to do something like:
3'b001: rgb <= "111110000000000";
And see if the blank screen turns red.

When debugging something with video, I tend to add some std_logic flags to show activity of particular circuit sections.
At the final VGA output section of the design, I override the output with a different pixel colour for each 'set' flag.
I've taken the idea a bit further with a simple logic analyzer component that I can drop into a design for a clearer view what's going on.


Mon Dec 11, 2017 7:47 am

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
Quote:
As a quick test I'd be tempted to do something like:
3'b001: rgb <= "111110000000000";
And see if the blank screen turns red.
/quote]That's a good test. The screen should only turn red when sprites are active then. So they should all show up as red boxes regardless of data coming from memory.
Quote:
When debugging something with video, I tend to add some std_logic flags to show activity of particular circuit sections.
At the final VGA output section of the design, I override the output with a different pixel colour for each 'set' flag.
I'm assuming here there'd be some `defines to strip the logic out once it's debugged ? Or does it just stay in as special test modes ?

Figured out that the black screen has to be another ram addressing problem. The color banding of memory worked. Color bands show up onscreen instead of blackness. That means the circuit isn’t accessing the right portion of the display ram. However it does seem to access the right memory for the first eight to ten scanlines of the display as when I hit reset the reset text appears on the top line of the display. So it’s accessing the right memory then. That means it can’t be the bitmap address changing because it’s extremely unlikely that if it changed it would change back to the correct address for the next display scan. That leaves only the ram address calc. For performance and power efficiency the ram address is calculated with a mac operation only at the start of a scanline. After that the address just increments. I’m guessing maybe the mac operation isn’t quite fast enough for the display. So that’s my next item to test. But it’s bizarre because it seems to be triggered when the sprite test is run. But there’s not supposed to be any hardware connection between the two. I'll throw in red box testing too, just to be sure. I suppose the problem could still be a giant sprite.

_________________
Robert Finch http://www.finitron.ca


Mon Dec 11, 2017 12:38 pm WWW

Joined: Fri May 08, 2015 6:22 pm
Posts: 61
robfinch wrote:
That's a good test. The screen should only turn red when sprites are active then. So they should all show up as red boxes regardless of data coming from memory.

It was the quickest way I could think of to test the giant sprite theory, though the same idea works for all sorts of things. When debugging a multiplexed memory system for example, it can be handy to light up a pixel in different colours for CS, WE, OE and other signals for a quick indicator of timing. Setting a pixel to a trace colour, along with using a flag triggered colour change will give you two pixels on the screen separated by the length of the pipeline. There are many other examples, VGA makes for a very handy debugging platform.

Quote:
I'm assuming here there'd be some `defines to strip the logic out once it's debugged ? Or does it just stay in as special test modes ?

In general I wouldn't need to have more than a few flags or debug hacks running at once, so they would sit there commented out when not in use.
I tend not to leave them around too long once a bug has fixed though, and can always refer to a previous version of the source to get them back.

Quote:
Figured out that the black screen has to be another ram addressing problem. The color banding of memory worked. Color bands show up onscreen instead of blackness. That means the circuit isn’t accessing the right portion of the display ram. However it does seem to access the right memory for the first eight to ten scanlines of the display as when I hit reset the reset text appears on the top line of the display. So it’s accessing the right memory then. That means it can’t be the bitmap address changing because it’s extremely unlikely that if it changed it would change back to the correct address for the next display scan. That leaves only the ram address calc. For performance and power efficiency the ram address is calculated with a mac operation only at the start of a scanline. After that the address just increments. I’m guessing maybe the mac operation isn’t quite fast enough for the display. So that’s my next item to test. But it’s bizarre because it seems to be triggered when the sprite test is run. But there’s not supposed to be any hardware connection between the two. I'll throw in red box testing too, just to be sure. I suppose the problem could still be a giant sprite.

You could modify your rainbow banding test to show the memory range that's being accessed, filling RAM with a colour based on it's upper address bits should provide some info, and it's still a rainbow, sort of.
It's an interesting bug, at least it act's in a predictable fashion. I'm not even sure this is a valid question, but what happens to the auto incrementing address when a sprite moves onto or off of the scanline currently being written. It might also be interesting to modify the sprite demo with a restraint keeping the sprites away from the screen edge by a certain number of pixels, this could rule out (or in) any quirky screen edge bugs.

Probably not a giant sprite if the screen didn't blank to red in the test.


Mon Dec 11, 2017 1:53 pm

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
Quote:
but what happens to the auto incrementing address when a sprite moves onto or off of the scanline

The address generator is super simple now. It either loads the sprite or display address, increments or does nothing. For sprites the address is set and modified during the horizontal blank time for every single scanline, it otherwise doesn't change. All the sprite data is read during horiz. blank into a buffer, then shifted out at the horizontal position of the sprite. At that point the address isn't changing. Sprite data can't be accessed during the display because the memory is busy with display data. The coordinates of the sprite can be set such that it's located in a border on the left or right and it will be hidden(there's about 60 clocks worth of space). There's only about 28 scanlines vertically to hide the sprite. So I think there may be display problems with a large sprite. But the border area is programmable so the viewport could be made smaller in order to hide sprites.
Code:
// Compute display ram index
always @(posedge clk)
begin
    casez({lowres,hpos})
    14'b??_1111_0011_1101: rdndx <= cursorWaddr[{1'b0,hpos[5:2]}+5'd1];
... 30 more sprite address loads
    14'b??_1111_1011_1001: rdndx <= cursorWaddr[{1'b1,hpos[5:2]}+5'd1];
    14'b00_1111_1111_1101: rdndx <= P0 + bmpBase;  //<- display scan load
    14'b01_1111_1111_1101: rdndx <= P1 + bmpBase;
    14'b10_1111_1111_1101: rdndx <= P2 + bmpBase;
    14'b00_1111_1111_1110: rdndx <= rdndx + 20'd1;
    14'b00_1111_1111_1111: rdndx <= rdndx + 20'd1;
    14'b??_1111_1111_1111: rdndx <= rdndx + 20'd1;
    14'b??_1111_????_????: rdndx <= rdndx + 20'd1;   // <- increment for sprite addressing
    14'b00_????_????_????: rdndx <= rdndx + 20'd1;
    14'b01_????_????_???1: rdndx <= rdndx + 20'd1;
    14'b10_????_????_??11: rdndx <= rdndx + 20'd1;
    default:    ;   // don't change rdndx
    endcase
end


Got the screen to appear as it should. Sprites gliding around the screen underneath the text display. Software now resets the bitmap address and width at vertical blank time. As far as I can tell there is no reason this should need to be done. The only thing I can think of is that noise is upsetting some of the bits in the bitmap address register, causing the wrong memory to be displayed. The only thing that writes the bitmap register is by the processor. The bitmap register isn’t supposed to be manipulated by hardware, it’s only read. It's almost as if there's an intermediate register that's failing. Bitmap address and bitmap width are used in a number of places. The register is likely replicated in hardware.

The only difference in software between the monitor running and the sprite demo is the address range of the boot rom. I could try moving the sprite demo in memory to see if it has an effect.

_________________
Robert Finch http://www.finitron.ca


Tue Dec 12, 2017 3:28 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
Filled triangle drawing is being added to the AV core. The core is currently setup to use the standard filled triangle draw method. The method relies on float math, but fixed point is used by the core as it’s probably sufficient for triangle drawing purposes. A 12 dot 16 fixed format is in use. The standard method breaks a triangle into two triangles, a flat bottom one and a flat top one and draws them both.
Test 1) nothing happens on screen, no triangles drawn the program finished almost instantly. -> it turns out I forgot to initialize the coordinates from the queue so they were assumed to be zero,, resulting in zero sized triangles being drawn.
Test 2) the triangle drawing fills the entire screen now. The test for end of triangle was bad. Neglected to use only the integer portion of the coordinate when comparing to the graphics cursor position.
Test 3) now the screen displays a mix of vertical lines and horizontal bars but no triangles
Test 4) after a number of fine-tuning adjustments in the comparisons of numbers and timing of operations, now a screen full of vertical lines appears. No more horizontal bars. It seems obvious that the slope of lines isn’t calculated correctly resulting in zero width triangles.
Test 5) after some research, found out the fixed point divide was wrong. The value needed to be shifted left a number of times first in order to get a non-zero value.

_________________
Robert Finch http://www.finitron.ca


Fri Dec 15, 2017 9:52 am WWW

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
It finally draws triangles but there is still a problem. Occasionally it only draws the outline of a triangle instead of filling it. <- This problem was fixed by swapping coordinates around.

Playing with clipping now. Added a graphics command to set the clip region for subsequent operations. Also added clipping to the size of the display bitmap.
Added Bezier curve drawing. This turned out to be easier than I thought it would be.

I realized when going to add coordinate transformations that I should've defined the coordinate system to be fixed point numbers rather than integers.
Just about time to re-write the core as it has several issues.

_________________
Robert Finch http://www.finitron.ca


Sat Dec 16, 2017 3:42 am WWW

Joined: Fri May 08, 2015 6:22 pm
Posts: 61
I'd had a few ideas but held them back they were mostly analogous to what you were already doing.

Do you really need floats, multiplying all integer coordinates by 4 before use might be enough. At final display time, you'd ignore the LSB's so as to match the screen co-ords.
Just off the top of my head, I think this should be equivalent to sampling an image at twice the Nyquist rate, so should prevent gaps (missed pixels) in the output image.

The 'standard method' for triangles uses floats, but there is also a Bresenham based algorithm for filled triangles.
http://www.sunshine2k.de/coding/java/Tr ... ation.html

Have you though about antialiased lines and shapes?
Have you been introduced to Mr. Wu?
https://en.wikipedia.org/wiki/Xiaolin_W ... _algorithm

Wu's line algorithm in many languages.
https://rosettacode.org/wiki/Xiaolin_Wu ... _algorithm

Wu's original antialiasing article.
http://www-users.mat.umk.pl/~gruby/teac ... m/1_wu.pdf


Sat Dec 16, 2017 7:42 am

Joined: Sat Feb 02, 2013 9:40 am
Posts: 1531
Location: Canada
I have now been introduced to Mr. Wu's anti-aliasing, but have yet to implement any.

The core now optionally passes points through a transform matrix before use. It should now be possible to do things like rotate text.

The command queue was re-written to accept 32 bit fixed point 16.16 coordinates. Rather than have a very wide command queue that could accommodate all parameters to all commands, the command queue width was reduced. Parameters must be placed independently on the command queue now. It’s slightly more program code, but also more flexible. Some of the extra code work was wrapped up into small macros.

A problem has arisen with point transformations. They don’t work with the blitter drawn rectangles :( If a rotation is supplied one would expect the rectangles to come out rotated, but the blitter only draws rectangles aligned with the display axis. Now I’m thinking of drawing rectangles as a pair of triangles that can be rotated. Reading up on rectangle drawing I found out most hardware doesn’t know about them. It only knows about points, lines, and triangles. So I will likely leave rectangle drawing up to software.

Triangle drawing is broken now since adapting coordinates to be 16.16 fixed point numbers. It almost works, drawing triangles but some extra horizontal lines are being drawn outside of the drawing area. Bezier curve drawing is also broken, I suspect for the same reason. It looks like testing the endpoints of lines is broken somehow.

I got the OLED display on the board going finally to display the address and data bus as the system is running. I had been scared away from it because it's quite complex compared to a bunch of seven segment displays. I was able to make use of a vendor supplied core to do most of the work.

_________________
Robert Finch http://www.finitron.ca


Sun Dec 17, 2017 3:08 pm WWW
 [ 70 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

Who is online

Users browsing this forum: CCBot and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software