diff --git a/gl/gl_def_cmd.sv b/gl/gl_def_cmd.sv index 68f79a15a3f7f2c168cbd9823315a9f562b66f92..68953dc7c8d2c2f508839943291fc0419ee9626c 100644 --- a/gl/gl_def_cmd.sv +++ b/gl/gl_def_cmd.sv @@ -4,6 +4,11 @@ // Commands `define GL_CMD_NOOP 4'h0 `define GL_CMD_RECT 4'h1 +`define GL_CMD_CIRCLE 4'h2 +`define GL_CMD_POLYGON 4'h3 +`define GL_CMD_STAR 4'h4 +`define GL_CMD_CURSOR 4'h5 +`define GL_CMD_IMAGE 4'h6 `define GL_CMD_FIN 4'hf `endif diff --git a/gl/gl_mgr.sv b/gl/gl_mgr.sv index 217a4c038edc84a9a4db895a1fbcca4ad611de39..bebc170ddef99409b8a0f9eb0f5234e21b1300b1 100644 --- a/gl/gl_mgr.sv +++ b/gl/gl_mgr.sv @@ -194,6 +194,8 @@ module gl_mgr ( end // GL Modules instances + + // Rectangle logic rect_en, rect_done; // Memory write connection logic rect_PAINT_REQ /*synthesis keep*/; @@ -214,6 +216,7 @@ module gl_mgr ( .C0 (GL_ARG3[15:0]), .C1 (GL_ARG3[31:16]), .GRAD_HORIZ (GL_ARG4[0]), + .CSTROKE (GL_ARG5[15:0]), .EN (rect_en), .DONE (rect_done), .PAINT_BUFFER (paint_buffer), @@ -228,6 +231,42 @@ module gl_mgr ( .RC_DATA_RD (rc_data_out1) ); + // Circle + logic circle_en, circle_done; + // Memory write connection + logic circle_PAINT_REQ /*synthesis keep*/; + logic [9:0] circle_PAINT_X, circle_PAINT_Y /*synthesis keep*/; + logic [15:0] circle_PAINT_RGB16 /*synthesis keep*/; + // Redraw cache connection + logic [18:0] circle_RC_ADDR; + logic circle_RC_DATA_WR; + logic circle_RC_WE; + logic circle_RC_DATA_RD; + gl_painter_circle painter_circle( + .CLOCK (CLOCK), + .RESET (RESET), + .X0 ({6'b0, GL_ARG1[19:10]}), + .Y0 ({6'b0, GL_ARG1[9:0]}), + .R ({6'b0, GL_ARG2[9:0]}), + .C0 (GL_ARG3[15:0]), + .C1 (GL_ARG3[31:16]), + .GRAD_HORIZ (GL_ARG4[0]), + .CSTROKE (GL_ARG5[15:0]), + .EN (circle_en), + .DONE (circle_done), + .PAINT_BUFFER (paint_buffer), + .fb_PAINT_REQ (circle_PAINT_REQ), + .fb_PAINT_X (circle_PAINT_X), + .fb_PAINT_Y (circle_PAINT_Y), + .fb_PAINT_RGB16(circle_PAINT_RGB16), + .fb_PAINT_READY(fb_PAINT_READY), + .RC_ADDR (circle_RC_ADDR), + .RC_DATA_WR (circle_RC_DATA_WR), + .RC_WE (circle_RC_WE), + .RC_DATA_RD (rc_data_out1) + ); + + always_comb begin // Route memory access @@ -254,5 +293,19 @@ module gl_mgr ( rect_en = 1'b0; end + if(GL_CMD == `GL_CMD_CIRCLE) begin + circle_en = GL_EXEC; + GL_DONE = circle_done; + fb_PAINT_REQ = circle_PAINT_REQ; + fb_PAINT_X = circle_PAINT_X; + fb_PAINT_Y = circle_PAINT_Y; + fb_PAINT_RGB16 = circle_PAINT_RGB16; + rc_addr1 = circle_RC_ADDR; + rc_data_in1 = circle_RC_DATA_WR; + rc_we1 = circle_RC_WE; + end else begin + circle_en = 1'b0; + end + end endmodule diff --git a/gl/oto_gl_hw.tcl b/gl/oto_gl_hw.tcl index f2c18f00abd104d8cfa1154eac89dc57b8a474b5..cb066edbfd501b0bdeb977c49890add472a94d82 100644 --- a/gl/oto_gl_hw.tcl +++ b/gl/oto_gl_hw.tcl @@ -1,11 +1,11 @@ # TCL File Generated by Component Editor 17.1 -# Wed Nov 29 09:34:49 CST 2017 +# Sat Dec 02 16:17:13 CST 2017 # DO NOT MODIFY # # oto_gl "otofpga Graphics Library" v1.0 -# 2017.11.29.09:34:49 +# 2017.12.02.16:17:13 # # @@ -49,6 +49,7 @@ add_fileset_file gl_redraw_cache.sv SYSTEM_VERILOG PATH gl_redraw_cache.sv add_fileset_file gl_sram_s.sv SYSTEM_VERILOG PATH gl_sram_s.sv add_fileset_file gl_vga.sv SYSTEM_VERILOG PATH gl_vga.sv add_fileset_file gl_painter_rect.sv SYSTEM_VERILOG PATH painters/gl_painter_rect.sv +add_fileset_file gl_painter_circle.sv SYSTEM_VERILOG PATH painters/gl_painter_circle.sv # diff --git a/gl/painters/gl_painter_circle.sv b/gl/painters/gl_painter_circle.sv new file mode 100644 index 0000000000000000000000000000000000000000..408c37c07090c953e76392c96ccd076419cbc3d7 --- /dev/null +++ b/gl/painters/gl_painter_circle.sv @@ -0,0 +1,203 @@ +module gl_painter_circle ( + // Clock + input logic CLOCK, RESET, + + // Arguments + input logic[15:0] X0, Y0, R, + input logic[15:0] C0, C1, CSTROKE, + input logic GRAD_HORIZ, + + // Status Control + input logic EN, + output logic DONE, + + input logic PAINT_BUFFER, + + // Memory write connection + output logic fb_PAINT_REQ, + output logic [9:0] fb_PAINT_X, fb_PAINT_Y, + output logic [15:0] fb_PAINT_RGB16, + input logic fb_PAINT_READY, + + // Redraw cache connection + output logic [19:0] RC_ADDR, + output logic RC_DATA_WR, + output logic RC_WE, + input logic RC_DATA_RD +); + logic [15:0] paint_x, paint_y; + logic [15:0] x, y, x_in, y_in, xlen, xlen_in; + logic [15:0] color, color_in; + logic paint_req_in; + enum logic[3:0] { + s_idle, s_axis, s_calc_xlen, s_paint, s_fin + } state, state_next; + logic[2:0] quadrant, quadrant_in; + + assign fb_PAINT_RGB16 = color; + assign RC_ADDR = {fb_PAINT_X, fb_PAINT_Y[8:0], PAINT_BUFFER}; + assign RC_DATA_WR = 1'b1; + + always_ff @(posedge CLOCK) begin + if(RESET | ~EN) begin + state <= s_idle; + quadrant <= 3'h0; + x <= 0; + y <= 0; + fb_PAINT_X <= X0; + fb_PAINT_Y <= Y0; + fb_PAINT_REQ <= 1'b0; + color <= C0; + xlen <= R; + end else begin + state <= state_next; + quadrant <= quadrant_in; + x <= x_in; + y <= y_in; + fb_PAINT_X <= X0 + paint_x; + fb_PAINT_Y <= Y0 + paint_y; + fb_PAINT_REQ <= paint_req_in; + color <= color_in; + state <= state_next; + xlen <= xlen_in; + end + end + + always_comb begin + // Default values + state_next = state; + quadrant_in = quadrant; + x_in = x; + y_in = y; + xlen_in = xlen; + color_in = color; + DONE = 1'b0; + RC_WE = 1'b0; + paint_req_in = 1'b0; + + case (state) + s_idle: begin + state_next = s_axis; + quadrant_in = 3'h0; + color_in = CSTROKE; + x_in = -R; + y_in = 0; + xlen_in = R; + paint_req_in = 1'b1; + end + + s_axis: begin + paint_req_in = 1'b1; + RC_WE = 1'b1; + if(fb_PAINT_READY) begin + // Value written, move to next pixel + x_in = x + 1; + if (x == R) begin + // Done. Draw next direction + x_in = -R; + y_in = 0; + quadrant_in = quadrant + 3'h1; + if (quadrant == 3'h1) begin + quadrant_in = 3'h0; + y_in = 1; + paint_req_in = 1'b0; + state_next = s_calc_xlen; + end + end + if (x_in == -R || x_in == R) + color_in = CSTROKE; + else + color_in = C0; + end + end + + s_calc_xlen: begin + if ((xlen*xlen + y*y) < R*R) begin + state_next = s_paint; + x_in = y; + paint_req_in = 1'b1; + end else begin + xlen_in = xlen - 1; + end + // End condition: went beyond 45 deg (has highest priority) + if (xlen < y) begin + state_next = s_fin; + end + end + + s_paint: begin + paint_req_in = 1'b1; + RC_WE = 1'b1; + if(fb_PAINT_READY) begin + // Value written, move to next pixel + x_in = x + 1; + if (x == xlen) begin + // Done. draw next quadrant + x_in = y; + quadrant_in = quadrant + 1; + if (quadrant == 3'h7) begin + // Drawing finished. Advance Y + y_in = y + 1; + state_next = s_calc_xlen; + paint_req_in = 1'b0; + end + end + if (x_in == xlen) + color_in = CSTROKE; + else + color_in = C0; + end + end + + s_fin: begin + DONE = 1'b1; + end + endcase + + // Quadrant coordinate mapping + unique case (quadrant) + 3'h0: begin + // Upper-right horizontal + paint_x = x_in; + paint_y = y_in; + end + 3'h1: begin + // Upper-right vertical + paint_x = y_in; + paint_y = x_in; + end + 3'h2: begin + // Upper-left vertical + paint_x = y_in; + paint_y = -x_in; + end + 3'h3: begin + // Upper-left horizontal + paint_x = -x_in; + paint_y = y_in; + end + 3'h4: begin + // Lower-left horizontal + paint_x = -x_in; + paint_y = -y_in; + end + 3'h5: begin + // Lower-left vertical + paint_x = -y_in; + paint_y = -x_in; + end + 3'h6: begin + // Lower-right vertical + paint_x = -y_in; + paint_y = x_in; + end + 3'h7: begin + // Lower-right horizontal + paint_x = x_in; + paint_y = -y_in; + end + endcase + + end + +endmodule diff --git a/gl/painters/gl_painter_rect.sv b/gl/painters/gl_painter_rect.sv index ae6c4f0a2728b6a17c97e73d60e7ad7219329c20..6f0288b5a32ebe69a2fb95f247af4e0799bd8df2 100644 --- a/gl/painters/gl_painter_rect.sv +++ b/gl/painters/gl_painter_rect.sv @@ -4,7 +4,7 @@ module gl_painter_rect ( // Arguments input logic[9:0] X0, Y0, X1, Y1 /*synthesis keep*/, - input logic[15:0] C0, C1, + input logic[15:0] C0, C1, CSTROKE, input logic GRAD_HORIZ, // Status Control @@ -20,7 +20,7 @@ module gl_painter_rect ( input logic fb_PAINT_READY, // Redraw cache connection - output logic [18:0] RC_ADDR, + output logic [19:0] RC_ADDR, output logic RC_DATA_WR, output logic RC_WE, input logic RC_DATA_RD @@ -28,9 +28,10 @@ module gl_painter_rect ( logic [9:0] x, y, x_in, y_in; logic [15:0] color, color_in; + logic paint_req_in; enum logic[3:0] { s_idle, s_paint, s_fin - } state, state_next /*synthesis keep*/; + } state, state_next; assign fb_PAINT_X = x; assign fb_PAINT_Y = y; @@ -43,11 +44,13 @@ module gl_painter_rect ( state <= s_idle; x <= X0; y <= Y0; - color <= C0; + fb_PAINT_REQ <= 1'b0; + color <= CSTROKE; end else begin state <= state_next; x <= x_in; y <= y_in; + fb_PAINT_REQ <= paint_req_in; color <= color_in; state <= state_next; end @@ -61,17 +64,18 @@ module gl_painter_rect ( color_in = color; DONE = 1'b0; RC_WE = 1'b0; - fb_PAINT_REQ = 1'b0; + paint_req_in = 1'b0; case (state) s_idle: begin state_next = s_paint; - color_in = C0; + color_in = CSTROKE; x_in = X0; y_in = Y0; + paint_req_in = 1'b1; end s_paint: begin - fb_PAINT_REQ = 1'b1; + paint_req_in = 1'b1; RC_WE = 1'b1; if(fb_PAINT_READY) begin // Value written, move to next pixel @@ -81,12 +85,15 @@ module gl_painter_rect ( x_in = x + 1; if (x == X1) begin // Done!!! - fb_PAINT_REQ = 1'b0; - RC_WE = 1'b0; + paint_req_in = 1'b0; state_next = s_fin; DONE = 1'b1; end end + if (x_in == X0 || x_in == X1 || y_in == Y0 || y_in == Y1) + color_in = CSTROKE; + else + color_in = C0; end end s_fin: begin diff --git a/software/osu_main/src/gl/gl.h b/software/osu_main/src/gl/gl.h index b0168dcad94aa8b085e7b2cef183947af2085bdc..4fd1caf4111a83fff3e68e10797493308423a576 100644 --- a/software/osu_main/src/gl/gl.h +++ b/software/osu_main/src/gl/gl.h @@ -6,6 +6,11 @@ #define GL_CMD_NOOP 0x0 #define GL_CMD_RECT 0x1 +#define GL_CMD_CIRCLE 0x2 +#define GL_CMD_POLYGON 0x3 +#define GL_CMD_STAR 0x4 +#define GL_CMD_CURSOR 0x5 +#define GL_CMD_IMAGE 0x6 #define GL_CMD_FIN 0xf void gl_wait(); diff --git a/software/osu_main/src/gl/painters.c b/software/osu_main/src/gl/painters.c index d6cd9da2233860713fda936edce7a292d79ea635..f4beb0396541683938d603b7e657094f789cc949 100644 --- a/software/osu_main/src/gl/painters.c +++ b/software/osu_main/src/gl/painters.c @@ -18,3 +18,17 @@ void gl_rect(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, GL_IOWR(GL_COMMAND, 0, GL_CMD_RECT); } +void gl_circle(uint16_t x0, uint16_t y0, uint16_t r, + uint16_t color0, uint16_t color1, uint16_t stroke, + uint8_t gradient_direction) { + gl_wait(); + + GL_IOWR(GL_ARGS, 0, gl_make_point(x0, y0)); + GL_IOWR(GL_ARGS, 1, r); + GL_IOWR(GL_ARGS, 2, (color1<<16) | color0); + GL_IOWR(GL_ARGS, 3, gradient_direction); + GL_IOWR(GL_ARGS, 4, stroke); + + GL_IOWR(GL_COMMAND, 0, GL_CMD_CIRCLE); +} + diff --git a/software/osu_main/src/main.c b/software/osu_main/src/main.c index 2ac51e303c4ec7439e39c278ab2ecdb232112920..795f0a03b03824a033720e800ca3a94bd90a03ae 100644 --- a/software/osu_main/src/main.c +++ b/software/osu_main/src/main.c @@ -64,7 +64,8 @@ int main() { printf("(%d, %d) wheel=%d btn=%x\n", x, y, sch, btn); } */ - gl_rect(25, 25, 200, 300, gl_make_color(0x66ccff), gl_make_color(0x66ccff), gl_make_color(0xffffff), 1); + gl_rect(25, 25, 40, 40, gl_make_color(0x66ccff), gl_make_color(0x66ccff), gl_make_color(0xffffff), 1); + gl_circle(200,200,50,gl_make_color(0x66ccff),gl_make_color(0x66ccff), gl_make_color(0xffffff), 1); gl_finalize_frame(); }