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();
 
 	}