Hmm.. okay, so I've downloaded the project, compiled and flashed it to the FPGA and downloaded and loaded the binaries into RS232_debugger. This is what I'm getting:
(Attachment Link)
I'm able to move it around, resize the overlay window etc. but I can't get a sensible image out of the overlay. I haven't changed anything, I've just copied the project into a new folder and compiled it in Quantus Prime. Also, it seems both quick binaries for the RS232_debugger are identical?
Hmm.. okay, so I've downloaded the project, compiled and flashed it to the FPGA and downloaded and loaded the binaries into RS232_debugger. This is what I'm getting:
(Attachment Link)
I'm able to move it around, resize the overlay window etc. but I can't get a sensible image out of the overlay. I haven't changed anything, I've just copied the project into a new folder and compiled it in Quantus Prime. Also, it seems both quick binaries for the RS232_debugger are identical?Did you program a paint software to draw in there?
Do you have the ram for a 256x256 pixel, 8 bit image?
Ok, maybe, first, you should add the the MAGGIE support for different bitplane sizes. This way, in 1 bit color, you could render the font in memory into the sprite if you made it 8 pixels wide with a 1 byte width setting for the graphics.
Looking at the code I sent you, and knowing where the pixels / bits setting is stored, show me how you would modify my MAGGIE code to recognizes the different bitplane modes horizontal sizes.
wire [1:0] pixel_per_byte;
assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)
assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)
if (run_x) begin
width <= width - 1;
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
end
Nope, you did great. I also would have accepted:
ram_read_pointer_x <= ram_read_pointer_x + ( 1 << pixel_per_byte );
Next, X - Zoom, or scale. Also known as X period or horizontal period.
The setting is stored in ' period_x[3:0] '.
The goal, when 'period_x[3:0]' = '0', the picture you get should be the same.
When 'period_x[3:0]' = '1' then the picture should be twice as wide, or, every X pixel is repeated twice.
When 'period_x[3:0]' = '2' then the picture should be 3 times as wide, or, every X pixel is repeated 3 times.
When 'period_x[3:0]' = '3' then the picture should be 4 times as wide, or, every X pixel is repeated 4 times.
......
When 'period_x[3:0]' = '7' then the picture should be 8 times as wide, or, every X pixel is repeated 8 times.
You get the idea.
wire [7:0] width_count; <----- new wire
if (run_x) begin
if (period_x[3:0] == width_count) begin
width <= width - 1;
width_count <= 0;
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
end
else begin
width_count <= width_count + 1;
ram_read_pointer_x <= ram_read_pointer_x;
end
end
Have you tried moving the text around inside a zoomed box with and without the original 'Y' code, taking care of the source read address, you will see a little problem...
Are you sure your width and height is correct ad 1x and 2x zooms?
Is the right read address getting through?
Change the base memory address to 0x0B10 & 0x0B00. Move it up and down 1 or 2 at different Y zoom levels 0 & 1. Something is off.
Your top line of the font is off by 1 byte as 0x0B0F renders the beginning of the character properly. And when zoomed, vertically to 1, you are also 1 line short at the bottom of the image. In fact, at all zoom levels above 0, you are missing 1 line at the bottom.
(I counted using the test vertical bar cursor at address 0x3F03)
Have you tried moving the text around inside a zoomed box with and without the original 'Y' code, taking care of the source read address, you will see a little problem...
Are you sure your width and height is correct ad 1x and 2x zooms?
Is the right read address getting through?
Change the base memory address to 0x0B10 & 0x0B00. Move it up and down 1 or 2 at different Y zoom levels 0 & 1. Something is off.
Your top line of the font is off by 1 byte as 0x0B0F renders the beginning of the character properly. And when zoomed, vertically to 1, you are also 1 line short at the bottom of the image. In fact, at all zoom levels above 0, you are missing 1 line at the bottom.
(I counted using the test vertical bar cursor at address 0x3F03)
Thought I was doing too well.
I've been staring at the code for the last 30 minutes and, short of randomly moving stuff about to test the results, I don't think I'm likely to spot the problem any time soon.
One thing I've found is that it's missing the first line even without the Y-scale code changes.
Is it because width[] and height[] are registers, and thus are a clock behind?
// **************************************************************
// * *
// * Multiple Address Generator & Graphics Instruction Engine *
// * *
// **************************************************************
module maggie (
//inputs
input wire clk,
input wire [3:0] pc_ena_in,
input wire [7:0] hw_regs[0:(2**HW_REGS-1)],
input wire [47:0] HV_trig,
input wire [31:0] cmd_in,
input wire [15:0] ram_din,
//outputs (all wires as we will embed the connected registers inside the module)
output wire [19:0] read_addr,
output wire [31:0] cmd_out,
output wire [23:0] bp_2_rast_cmd
);
// parameters
parameter HW_REGS = 8;
parameter HW_REG_BASE = 96;
parameter H_RESET_TRIG = 8;
parameter H_POS_TRIG = 10;
parameter RAM_READ_CYCLES = 3;
// local parameters
localparam V_RESET_TRIG = H_RESET_TRIG + 1;
localparam V_POS_TRIG = H_POS_TRIG + 1;
localparam BP2RAST_cmd = HW_REG_BASE + 0; // Transfers the video mode setting to the new bitplane_2_raster module
localparam BP2RAST_bgc = HW_REG_BASE + 1; // Transfers the bg_colour setting to the new bitplane_2_raster module
localparam BP2RAST_fgc = HW_REG_BASE + 2; // Transfers the fg_colour setting to the new bitplane_2_raster module
localparam RST_ADDR_H = HW_REG_BASE + 3; // MSB bits of 24 bit base read address
localparam RST_ADDR_M = HW_REG_BASE + 4; // MID bits of 24 bit base read address
localparam RST_ADDR_L = HW_REG_BASE + 5; // LSB bits of 24 bit base read address
localparam YINC_ADDR_H = HW_REG_BASE + 6; // MSB bits of 16 bit Y-Line increment for read address
localparam YINC_ADDR_L = HW_REG_BASE + 7; // LSB bits of 16 bit Y-Line increment for read address
localparam X_SIZE_H = HW_REG_BASE + 8; // MSB bits of 16 bit display width screen pixels
localparam X_SIZE_L = HW_REG_BASE + 9; // LSB bits of 16 bit display width screen pixels
localparam Y_SIZE_H = HW_REG_BASE + 10; // MSB bits of 16 bit display height screen y lines
localparam Y_SIZE_L = HW_REG_BASE + 11; // LSB bits of 16 bit display height screen y lines
localparam X_SCALE = HW_REG_BASE + 12; // Compound of two 4 bit words. Upper 4 bits controls the X increment every period, lower 4 bits is a pixel period counter to define the number of pixels until the upper 4 bits are added to the address-pointer.
localparam Y_SCALE = HW_REG_BASE + 13; // Compound of two 4 bit words. Upper 4 bits reserved for text tile mode Y size while the lower lower 4 bits is a line period counter to define the number of lines until YINC_ADDR is added to the address-pointer
localparam X_START_SUB = HW_REG_BASE + 14; // An 8 bit word which defines an odd pixel start position within the period counter and X position within a bitplane's X coordinate position
localparam Y_START_SUB = HW_REG_BASE + 15; // An 8 bit word which defines an odd line start within within the period counter and Y coordinates inside a font.
// registers
reg [19:0] ram_read_pointer_y;
reg [23:0] ram_read_pointer_x;
reg [4:0] period_x;
reg [4:0] period_y;
reg [7:0] h_trig_delay;
reg [11:0] width;
reg [11:0] height;
wire run_x;
wire run_y;
assign run_x = width[11];
assign run_y = height[11];
// wires
wire h_rst, x_rst, xy_rst;
wire h_trig, v_trig;
wire window_enable;
wire [23:0] reset_addr;
wire [15:0] inc_addr_x;
wire [15:0] inc_addr_y;
wire [3:0] period_x_rst;
wire [3:0] period_y_rst;
wire [11:0] x_size;
wire [11:0] y_size;
wire [1:0] pixel_per_byte;
wire [7:0] width_count;
wire [7:0] height_count;
// assignments
assign bp_2_rast_cmd[23:0] = { hw_regs[BP2RAST_fgc] , hw_regs[BP2RAST_bgc] , hw_regs[BP2RAST_cmd] };
assign text_mode_master = hw_regs[BP2RAST_cmd][7];
assign x_rst = HV_trig[H_RESET_TRIG];
assign xy_rst = HV_trig[V_RESET_TRIG] && x_rst;
assign v_trig = HV_trig[V_POS_TRIG];
assign h_trig = HV_trig[H_POS_TRIG];
assign h_rst = text_mode_master ? h_trig_delay[0] : h_trig_delay[RAM_READ_CYCLES-1]; // When in text mode, push the window left by 'RAM_READ_CYCLES' as it takes a second memory read to get the font image
assign window_enable = run_x && run_y;
assign cmd_out[7] = window_enable; // commands the pixel/by/pixel window enable for the bitplane_2_raster module
assign cmd_out[6] = 1'b0; // for now, disables the 2 byte colour mode
assign reset_addr[23:0] = { hw_regs[RST_ADDR_H] , hw_regs[RST_ADDR_M] , hw_regs[RST_ADDR_L] };
assign inc_addr_y[15:0] = { hw_regs[YINC_ADDR_H] , hw_regs[YINC_ADDR_L] };
assign inc_addr_x[3:0] = hw_regs[X_SCALE][7:4];
assign read_addr[19:0] = ram_read_pointer_x[22:3];
assign cmd_out[2:0] = ram_read_pointer_x[2:0]; // commands the sub pixel X position for the bitplane_2_raster module
assign period_x[3:0] = hw_regs[X_SCALE][3:0];
assign period_y[3:0] = hw_regs[Y_SCALE][3:0];
assign period_x_rst[3:0] = hw_regs[X_START_SUB][3:0];
assign period_y_rst[3:0] = hw_regs[Y_START_SUB][3:0];
assign x_size[11:0] = { hw_regs[X_SIZE_H][3:0], hw_regs[X_SIZE_L][7:0] };
assign y_size[11:0] = { hw_regs[Y_SIZE_H][3:0], hw_regs[Y_SIZE_L][7:0] };
assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)
always @(posedge clk) begin
if (pc_ena_in[3:0] == 0) begin
h_trig_delay[7:1] <= h_trig_delay[6:0];
h_trig_delay[0] <= h_trig;
if (xy_rst) begin // equivalent to a vertical sync/reset
height <= 0;
width_count <= 0;
height_count <= 0;
end
else if (x_rst) begin // equivalent to a horizontal sync/increment
width <= 0;
width_count <= 0;
if (v_trig) begin // V_TRIG is high for the entire first line of video to be displayed. This is the point in place and time where the read address must be equal to the setting in the reset_addr.
height[11] <= 1; // set run_y bit active
height[10:0] <= y_size[10:0];
height_count <= 0; // * must reset as well.
ram_read_pointer_y <= reset_addr << 3; // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= reset_addr << 3; // the backup and currrent display address to the exact reset base address during this line.
end // V_TRIG
else begin // ~V_TRIG
if (run_y) begin // after the first line, do these functions.
if (period_y[3:0] == height_count) begin // If the vertical scale period count has reached it's end
height <= height - 1; // count down the visible window size
height_count <= 0; // reset the vertical period
ram_read_pointer_y <= ram_read_pointer_y + (inc_addr_y[15:0] << 3); // vertical increment display position in backup buffer
ram_read_pointer_x <= ram_read_pointer_y + (inc_addr_y[15:0] << 3); // vertical increment display position in current display address
end // (period_y[3:0] == height_count
else begin // if the period count hasn't reached it's end,
height_count <= height_count + 1; // increment the period count
ram_read_pointer_x <= ram_read_pointer_y; // restore the memory read address to the previous backup buffer address
end
end // ~V_TRIG
end
end
else begin
if (h_rst) begin
width[11] <= 1; // set run_x bit active
width[10:0] <= x_size[10:0];
width_count <= 0;
end
if (run_x) begin
if (period_x[3:0] == width_count) begin
width <= width - 1;
width_count <= 0;
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
end
else begin
width_count <= width_count + 1;
end
end
//-------------------------------
//snap to it....
//-------------------------------
end // ~x_rst
end // if (pc_ena_in[3:0] == 0)
end //@(posedge clk)
endmodule
Okay, I've had 10 minutes to look at this, so don't be too critical. This is what I've come up with:Code: [Select]assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)
So now pixel_per_byte relates directly to the current mode. Further down, in the always @(posedge clk) block, I've tweaked the ram_read_pointer_x increment to be sensitive to the current mode:
assign pixel_per_byte = bp_2_rast_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)
The 4 files are:
z80_360x256x1.bin
pac_208x204x4.bin
z80_192x120x16.bin
z80_120x96x256.bin
I tested them all ok, so I expect proper screen shots. You will need to figure out the MAGGIE settings for the X&Y resolution by # of colors.
The 4 files are:
z80_360x256x1.bin
pac_208x204x4.bin
z80_192x120x16.bin
z80_120x96x256.bin
I tested them all ok, so I expect proper screen shots. You will need to figure out the MAGGIE settings for the X&Y resolution by # of colors.
Here's what I've got - the palette is out mostly, but I think I can decipher the images:
z80_360x256x1.bin:
(Attachment Link)
pac_208x204x4.bin:
(Attachment Link)
z80_192x120x16.bin:
(Attachment Link)
z80_120x96x256.bin: (I moved the sprite down out of the way of the garbage text above it)
(Attachment Link)
The images are appearing BEHIND the text though - is there a setting I'm missing somewhere?
You couldn't choose a better set of colors, like White and Black?
Remmeber, bg_color anf FG_color...
What about turning off the text layer?
Remember, the old bitplane_to_raster controls...
You couldn't choose a better set of colors, like White and Black?
Remmeber, bg_color anf FG_color...
What about turning off the text layer?
Remember, the old bitplane_to_raster controls...
I was just interested in getting the images to show, and to make the text overlapping the sprites visible. I know I can turn the text off, just wondered if the 'z-order' of the drawing was correct and intended, that's all?
(Attachment Link)
ram_read_pointer_x <= ram_read_pointer_x + (x_size * y_size) + x_size*((1 << y_size[7:4]) - 1) + 1 + y_size[7:4];
Well, that got weird fast...
I had a think about how best to implement horizontal scrolling as you've stated:
(Attachment Link)
Being more of someone who learns by experimentation, I cracked on and started writing code to get the sprite going horizontally, tweaking and adding bits to get the desired output. I decided to stop when I realised I hadn't a clue what I was doing anymore and the sprite wasn't scrolling horizontally properly for every height it could have.Code: [Select]ram_read_pointer_x <= ram_read_pointer_x + (x_size * y_size) + x_size*((1 << y_size[7:4]) - 1) + 1 + y_size[7:4];
Can't be good when it starts to get that complicated and it still doesn't cover sizes of Y above 0x20.
Full code for MAGGIE attached so you can see what a convoluted mess I've made with my attempt.
You only needed 8 pixels. Your Z80 fills in the reset address. This is all you should have written:
Lines 137 & 138: (undo your other changes)
ram_read_pointer_y <= (reset_addr << 3) + period_x_rst; // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= (reset_addr << 3) + period_x_rst; // the backup and current display address to the exact reset base address during this line.
This allows byte/bitplane sub-pixel horizontal alignment along the X-axis when the sprite begins it's first pixel. If you like, there is the potential to add 1 other thing to make this add always = to 1 pixel when dealing with 4 color and 16 bit color. It's useless with 256 color at the base address increments as 1 for moving the image 1 pixel.
Next, the really weird 16 bit pixel mode. Add this assign:
assign pixel_16_bit = bp_2_rast_cmd[2]; // setting goes high when we expect 16 bit, 2 byte pixels.
Now, what this setting does is when set to 1, every time the 'X' read address increases, it will need to increase by 2, not 1 as it currently does. If you truly figure the really simple way to get this one to work right, you will get a prize... Remember, that 'Increment by 2' doe not affect the lower 3 bits which horizontally position the bitplane sub-pixel positioning.
ram_read_pointer_y <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 + pixel_16_bit)); // vertical increment display position in backup buffer
ram_read_pointer_x <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 + pixel_16_bit)); // vertical increment display position in current display address
You only needed 8 pixels. Your Z80 fills in the reset address. This is all you should have written:
Lines 137 & 138: (undo your other changes)
ram_read_pointer_y <= (reset_addr << 3) + period_x_rst; // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= (reset_addr << 3) + period_x_rst; // the backup and current display address to the exact reset base address during this line.
This allows byte/bitplane sub-pixel horizontal alignment along the X-axis when the sprite begins it's first pixel. If you like, there is the potential to add 1 other thing to make this add always = to 1 pixel when dealing with 4 color and 16 bit color. It's useless with 256 color at the base address increments as 1 for moving the image 1 pixel.
... but that doesn't do what I thought you wanted? I had in mind, for example for an 8x16 sprite, it would show the letter 'A' and when you scroll it, it would scroll to the left and show the letter 'B' coming in from the right, stopping one pixel short of showing the full tile (for the Z80 to re-set the start address and show the next char completely)?
Also, the 'new' tile scrolling in from the right is moved up a line? Is that intended?
Next, the really weird 16 bit pixel mode. Add this assign:
assign pixel_16_bit = bp_2_rast_cmd[2]; // setting goes high when we expect 16 bit, 2 byte pixels.
Now, what this setting does is when set to 1, every time the 'X' read address increases, it will need to increase by 2, not 1 as it currently does. If you truly figure the really simple way to get this one to work right, you will get a prize... Remember, that 'Increment by 2' doe not affect the lower 3 bits which horizontally position the bitplane sub-pixel positioning.
Erm... well, I'd change lines 151 and 152 to this:Code: [Select]ram_read_pointer_y <= ram_read_pointer_y + ((inc_addr_y[15:0] << 3) * (1+pixel_16_bit)); // vertical increment display position in backup buffer
ram_read_pointer_x <= ram_read_pointer_y + ((inc_addr_y[15:0] << 3) * (1+pixel_16_bit)); // vertical increment display position in current display address
Latest MAGGIE code attached.
EDIT: Hang on - testing a simpler way to do the 16-bit scroll..