From ebbbc44cbca9d88eceef9be027d4cac6e151e8e4 Mon Sep 17 00:00:00 2001
From: madonius <info-card10@kampitakis.de>
Date: Mon, 22 Jul 2019 15:50:04 +0000
Subject: [PATCH] feat(display): Add method to set a single pixel

---
 epicardium/epicardium.h         | 18 ++++++++++++++++++
 epicardium/modules/display.c    | 11 +++++++++++
 pycardium/modules/py/display.py | 14 ++++++++++++++
 pycardium/modules/qstrdefs.h    |  1 +
 pycardium/modules/sys_display.c | 27 +++++++++++++++++++++++++++
 5 files changed, 71 insertions(+)

diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 4ded292b..cf7a7f35 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -44,6 +44,7 @@ typedef unsigned int size_t;
 #define API_DISP_LINE          0x15
 #define API_DISP_RECT          0x16
 #define API_DISP_CIRC          0x17
+#define API_DISP_PIXEL         0x18
 /* clang-format on */
 
 typedef uint32_t api_int_id_t;
@@ -307,6 +308,23 @@ API(API_DISP_PRINT,
  */
 API(API_DISP_CLEAR, int epic_disp_clear(uint16_t color));
 
+/**
+ * Draws a pixel on the display
+ *
+ * :param x: x position; 0 <= x <= 160
+ * :param y: y position; 0 <= y <= 80
+ * :param color: pixel color in rgb565
+ * :return: ``0`` on success or a negative value in case of an error:
+ *
+ *    - ``-EBUSY``: Display was already locked from another task.
+ */
+API(API_DISP_PIXEL,
+    int epic_disp_pixel(
+	    uint16_t x,
+	    uint16_t y,
+	    uint16_t color)
+    );
+
 /**
  * Draws a line on the display
  *
diff --git a/epicardium/modules/display.c b/epicardium/modules/display.c
index 26db0d13..1786d805 100644
--- a/epicardium/modules/display.c
+++ b/epicardium/modules/display.c
@@ -46,6 +46,17 @@ int epic_disp_clear(uint16_t color)
 	}
 }
 
+int epic_disp_pixel(uint16_t x, uint16_t y, uint16_t color)
+{
+	int cl = check_lock();
+	if (cl < 0) {
+		return cl;
+	} else {
+		Paint_SetPixel(x, y, color);
+		return 0;
+	}
+}
+
 int epic_disp_line(
 	uint16_t xstart,
 	uint16_t ystart,
diff --git a/pycardium/modules/py/display.py b/pycardium/modules/py/display.py
index 2f7f85a8..ebb27636 100644
--- a/pycardium/modules/py/display.py
+++ b/pycardium/modules/py/display.py
@@ -76,6 +76,20 @@ class Display:
         sys_display.print(text, posx, posy, fg, bg)
         return self
 
+    def pixel(self, x, y, *, col=None):
+        """
+        Draws a pixel on the display
+
+        :param x: X coordinate, 0<= x <= 160
+        :param y: Y coordinate, 0<= y <= 80
+        :param col: color of the pixel (expects RGB tripple)
+        """
+
+        col = col or color.WHITE
+
+        sys_display.pixel(x, y, col)
+        return self
+
     def line(self, xs, ys, xe, ye, *, col=None, dotted=False, size=1):
         """
         Draws a line on the display.
diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h
index 61ee2c74..707a27af 100644
--- a/pycardium/modules/qstrdefs.h
+++ b/pycardium/modules/qstrdefs.h
@@ -35,6 +35,7 @@ Q(BHI160)
 Q(sys_display)
 Q(display)
 Q(print)
+Q(pixel)
 Q(line)
 Q(rect)
 Q(circ)
diff --git a/pycardium/modules/sys_display.c b/pycardium/modules/sys_display.c
index 1e5d61d3..96cdcb01 100644
--- a/pycardium/modules/sys_display.c
+++ b/pycardium/modules/sys_display.c
@@ -49,6 +49,29 @@ static mp_obj_t mp_display_print(size_t n_args, const mp_obj_t *args)
 	return mp_const_none;
 }
 
+/* draw pixel on the display */
+static mp_obj_t mp_display_pixel(size_t n_args, const mp_obj_t *args)
+{
+	uint16_t x   = mp_obj_get_int(args[0]);
+	uint16_t y   = mp_obj_get_int(args[1]);
+	uint16_t col = get_color(args[2]);
+
+	//TODO: Move sanity checks to epicardium
+	if (x > 160 || x < 0) {
+		mp_raise_ValueError("X-Coords have to be 0 < x < 160");
+	}
+
+	if (y > 80 || y < 0) {
+		mp_raise_ValueError("Y-Coords have to be 0 < y < 80");
+	}
+
+	int res = epic_disp_pixel(x, y, col);
+	if (res < 0) {
+		mp_raise_OSError(-res);
+	}
+	return mp_const_none;
+}
+
 /* draw line on the display */
 static mp_obj_t mp_display_line(size_t n_args, const mp_obj_t *args)
 {
@@ -174,6 +197,9 @@ static mp_obj_t mp_display_close()
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
 	display_print_obj, 5, 5, mp_display_print
 );
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
+	display_pixel_obj, 3, 3, mp_display_pixel
+);
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
 	display_line_obj, 7, 7, mp_display_line
 );
@@ -194,6 +220,7 @@ static const mp_rom_map_elem_t display_module_globals_table[] = {
 	{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&display_open_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&display_close_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&display_print_obj) },
+	{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&display_pixel_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&display_line_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&display_rect_obj) },
 	{ MP_ROM_QSTR(MP_QSTR_circ), MP_ROM_PTR(&display_circ_obj) },
-- 
GitLab