Archive - April 2017

1
move.w vs move.l: The culprit of my circle problems
2
Graphics Primitives are working, at least mostly.
3
Frame Buffer and Text Generation now working…
4
Interesting snippet from FPGA Prototyping by Chu
5
SRAM Frame Buffer is now up and running!

move.w vs move.l: The culprit of my circle problems

If you saw my recent post about malformed circles, you’ll see that I was pulling my hair out.

I identified the root cause. It turns out that I was writing 0x00000fff, which caused the pixel I was setting to be black, 0x0000. Worst of all, it was also writing the pixel next to it! It was writing 0x0FFF to the pixel to the right, which causes the pixel to the right to be all white. Pretty insidious! Had it not produced anything on the display, surely I would have tracked down this sooner.

I’ve been playing around with a variety of solutions, and compiled the midpoint circle algorithm C code into assembly, and the move.l instruction was created by the compiler, from my faulty C code.

The correct instruction was one that just modified the 16-bit word at the address in question, the move.w #$0fff, (a4) instruction. The other one, the move.l #4095, (a5) was the problem one.

UPDATE: Just to be clear, there’s no problem or bug with the compiler. I used the wrong data type, likely a 32-bit int or similar(or perhaps a uncast constant assumed to be 32-bit), in the C code, which caused the unwanted move.l instruction to be created. This was entirely my fault. For what it’s worth, this is my first time with more than 10 lines of 68K assembly in decades. I wasn’t good back then, either. 🙂

I still have to create a toolchain for my machine. Remember there are no sample programs, no documentation, no faq’s, so I’m still figuring out how all of this works. I don’t have a properly configured C compiler, with memory areas dedicated for stack, heap, and lord knows whatever else I have to configure. I’m happy to be turning the corner from hardware development to something that is actually USABLE from a software developer perspective.

 

Graphics Primitives are working, at least mostly.

So we’ve got a frame buffer now which means we can start writing 68K routines to write graphics into it.

So here I’m playing around with lines and circles. I’m using a random line drawing routine from the Atari that I found. I’m using the C code from the Midpoint Circle Algorithm on wikipedia, that has been compiled, and then has the assembly modified to work without support for negative numbers.

I’m seeing some graphic defect, but I’m not sure if that’s due to

  • A defect in the assembly of the Midpoint Circle algorithm
  • An existing cpu write problem (sharing SRAM)
  • a video display issue (also sharing SRAM)
  • an artifact of the built-in monitor upscaling algorithm

The C code runs fine in windows without any similar effect.

Here’s the code:

; }
; void drawcircle(short x0,short y0,short radius)
; {
_drawcircle:
lea _putpixel.L,A2
; short y = 0;
clr.w D2
; short err = 0;
;clr.w D6
move.l #$8000, D6 ; this is an arbitrary number since we can't easily handle negative numbers.
; while (x >= y)
drawcircle_1:
cmp.w D2,D3
blt drawcircle_3
; {
; putpixel(x0 + x, y0 + y);
move.w D5,D0
add.w D2,D0
ext.l D0
move.w D4,D1
add.w D3,D1
ext.l D1
jsr (A2)

; putpixel(x0 + y, y0 + x);
move.w D5,D0
add.w D3,D0
ext.l D0
move.w D4,D1
add.w D2,D1
ext.l D1
jsr (A2)

; putpixel(x0 - y, y0 + x);
move.w D5,D0
add.w D3,D0
ext.l D0
move.w D4,D1
sub.w D2,D1
ext.l D1
jsr (A2)

; putpixel(x0 - x, y0 + y);
move.w D5,D0
add.w D2,D0
ext.l D0
move.w D4,D1
sub.w D3,D1
ext.l D1
jsr (A2)

; putpixel(x0 - x, y0 - y);
move.w D5,D0
sub.w D2,D0
ext.l D0
move.w D4,D1
sub.w D3,D1
ext.l D1
jsr (A2)

; putpixel(x0 - y, y0 - x);
move.w D5,D0
sub.w D3,D0
ext.l D0

move.w D4,D1
sub.w D2,D1
ext.l D1
jsr (A2)

; putpixel(x0 + y, y0 - x);
move.w D5,D0
sub.w D3,D0
ext.l D0
move.w D4,D1
add.w D2,D1
ext.l D1
jsr (A2)

; putpixel(x0 + x, y0 - y);
move.w D5,D0
sub.w D2,D0
ext.l D0
move.w D4,D1
add.w D3,D1
ext.l D1
jsr (A2)

; if (err <= 0) cmp.l #$8000,D6 bgt.s drawcircle_4 ; { ; y += 1; addq.w #1,D2 ; err += 2*y + 1; move.w D2,D0 asl.l #1,D0 addq.w #1,D0 add.w D0,D6 drawcircle_4: ; } ; if (err > 0)
cmp.l #$8000,D6
ble.s drawcircle_6
; {
; x -= 1;
subq.w #1,D3
; err -= 2*x + 1;
move.w D3,D0
asl.l #1,D0
addq.w #1,D0
sub.w D0,D6
drawcircle_6:
bra drawcircle_1
drawcircle_3:
rts

You also see a remnant from my previous text generation in the upper left hand corner.

I’m open to thoughts on the circle problem!

Frame Buffer and Text Generation now working…

Now that I have the 4MB SRAM board installed, I now have a frame buffer that can keep up with the video bandwidth rate.

The resolution and color depth is currently 800 x 480 x 12-bit. The computing shield I’m using only supports 12-bits, but my LCD can do 24-bit.

Essentially how my frame buffer works is that you write the 12-bit color value into an address in memory that corresponds to a location on the screen.

See Framebuffer at Wikipedia.

The 4MB SRAM gets mapped to $820 000. The color values are stored as 16-bit words like this 0000_RRRR_GGGG_BBBB. Top 4 bits are not used, for now.

One 68K instruction, for example,  “move.w #$0F00,$820000” will put a single red pixel, at location 0,0.

I also have text generation working:

This works a similar way with a character buffer. Another part of ram is being used to store a 100 x 30 character buffer. If you write a 7-bit ASCII value to the lower portion of a 16-bit word at an address that corresponds to the location, then that character will be displayed.

The text layer is independent of the frame buffer, and is overlaid on top of that graphics layer.

This adds pretty powerful capabilities to the badge computer, and now I have to start writing some utility routines to do higher level functions like drawing a line or a circle.

 

Interesting snippet from FPGA Prototyping by Chu

This is exactly the problem that I’ve been facing for the last couple weeks. I could get the memory tests to pass at 100% if only the CPU was talking with the external SRAM. As soon as I added in my time slot system, where every other cycle is for the CPU and the video display circuit, then the test would fail miserably.

What I settled on was simply disabling access to the SRAM from the video display during the fairly short interval that the CPU was accessing. This guarantees that the CPU has relatively error free access. The suggestion above is to only allow writing video memory during the blanking interval, and I think that’s a good idea too.

I still see some small percentage of errors both on the CPU side and the video driver side, but the rate is small enough to not cause any problems currently.

I’ll revisit this noise issue later, but for now, it kinda gives a little Max Headroom kinda vibe to the project, and I like this!

For what it’s worth, knowing that the “struggle is real” and that what I’m dealing with is a conventional problem is refreshing. I’m sure the early computer designers also ran into problems…..

SRAM Frame Buffer is now up and running!

Exciting times for the Hope Badge Computer.

Tonight, I’ve worked out most of the kinks with interfacing the new SRAM module which you can see in posts below this, to the J68 soft-core CPU.

This means that I can now write to memory locations using 68000 assembly, and display color graphics on the screen.

The current resolution is 800 x 480, which matches the LCD. I have attached a VGA LCD Monitor to the FPGA. That interface, the computing shield that you can also see a couple posts down, uses a 12-bit DAC, therefore, the current color depth is 12-bits. Which works out to be 4096 colors. I can support 16-bits on the 7.0 touchscreen, or 16-bits using a better/different DAC for VGA. This is without any other modifications.

The plan is to get to 24-bit color, but everything in due time!

Time to start practicing my 68K assembly!