From 4012a45144b4936d172c41646c5157e2787b92bd Mon Sep 17 00:00:00 2001
From: Sergiusz Bazanski <q3k@q3k.org>
Date: Sun, 28 Jul 2019 21:30:12 +0200
Subject: [PATCH] lib/gfx,epicardium: implement FB API, fix SPI IRQ

---
 epicardium/epicardium.h      |  9 ++++++++-
 epicardium/modules/display.c |  5 +++++
 lib/card10/display.c         |  3 +++
 lib/gfx/GUI_DEV/DEV_Config.c | 18 +++++++++++++++++-
 lib/gfx/GUI_DEV/DEV_Config.h |  6 ++++--
 lib/gfx/LCD/LCD_Driver.c     | 10 ++++------
 lib/gfx/LCD/LCD_Driver.h     |  5 +++++
 7 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 9c4a770d..09151042 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -48,6 +48,7 @@ typedef unsigned int size_t;
 #define API_DISP_RECT          0x16
 #define API_DISP_CIRC          0x17
 #define API_DISP_PIXEL         0x18
+#define API_DISP_FRAMEBUFFER   0x19
 
 #define API_FILE_OPEN          0x30
 #define API_FILE_CLOSE         0x31
@@ -288,7 +289,6 @@ API(API_DISP_CLOSE, int epic_disp_close());
  * to be shown on the display
  */
 API(API_DISP_UPDATE, int epic_disp_update());
-
 /**
  * Prints a string into the display framebuffer
  *
@@ -410,6 +410,13 @@ API(API_DISP_CIRC,
 	    uint16_t pixelsize)
     );
 
+/**
+ * Returns the back framebuffer (the display buffer that's currently inactive
+ * that will be shown after the next call to ``epic_disp_update``.
+ */
+API(API_DISP_FRAMEBUFFER, uint16_t *epic_disp_framebuffer());
+
+
 /**
  * Start continuous readout of the light sensor. Will read light level
  * at preconfigured interval and make it available via `epic_light_sensor_get()`.
diff --git a/epicardium/modules/display.c b/epicardium/modules/display.c
index 1786d805..2cabe397 100644
--- a/epicardium/modules/display.c
+++ b/epicardium/modules/display.c
@@ -125,6 +125,11 @@ int epic_disp_update()
 	}
 }
 
+uint16_t *epic_disp_framebuffer()
+{
+	return (uint16_t*) LCD_Framebuffer();
+}
+
 int epic_disp_open()
 {
 	TaskHandle_t task = xTaskGetCurrentTaskHandle();
diff --git a/lib/card10/display.c b/lib/card10/display.c
index e1d66276..9db6e29e 100644
--- a/lib/card10/display.c
+++ b/lib/card10/display.c
@@ -1,5 +1,6 @@
 #include "LCD/LCD_Driver.h"
 #include "GUI_DEV/GUI_Paint.h"
+#include "GUI_DEV/DEV_Config.h"
 
 #include "gpio.h"
 #include "tmr.h"
@@ -81,6 +82,8 @@ void display_set_reset_pin(uint8_t state)
 
 void display_init(void)
 {
+	lcd_irq_init();
+
 	if (!portexpander_detected()) {
 		// Open-drain
 		MAX77650_setDRV(false);
diff --git a/lib/gfx/GUI_DEV/DEV_Config.c b/lib/gfx/GUI_DEV/DEV_Config.c
index 5c1e4b22..7a09c400 100644
--- a/lib/gfx/GUI_DEV/DEV_Config.c
+++ b/lib/gfx/GUI_DEV/DEV_Config.c
@@ -39,7 +39,7 @@
 static spi_req_t req = {.rx_data = NULL, .bits=8, .width = SPI17Y_WIDTH_1, .ssel = 0, .deass = 1, .ssel_pol = SPI17Y_POL_LOW, .tx_num = 0, .rx_num = 0};
 
 /********************************************************************************/
-void lcd_write(uint8_t *data, int size, lcd_write_cb_t wr_callback)
+void lcd_write_async(uint8_t *data, int size, lcd_write_cb_t wr_callback)
 {
     req.tx_data = data;
     req.len = size;
@@ -47,3 +47,19 @@ void lcd_write(uint8_t *data, int size, lcd_write_cb_t wr_callback)
     SPI_MasterTransAsync(SPI, &req);
 }
 
+void lcd_write(uint8_t *data, int size)
+{
+    req.tx_data = data;
+    req.len = size;
+    SPI_MasterTrans(SPI, &req);
+}
+
+void lcd_irq_init(void)
+{
+    NVIC_EnableIRQ(SPI2_IRQn);
+}
+
+void SPI2_IRQHandler(void)
+{
+    SPI_Handler(SPI);
+}
diff --git a/lib/gfx/GUI_DEV/DEV_Config.h b/lib/gfx/GUI_DEV/DEV_Config.h
index 5e4ed5f7..7308bf02 100644
--- a/lib/gfx/GUI_DEV/DEV_Config.h
+++ b/lib/gfx/GUI_DEV/DEV_Config.h
@@ -59,9 +59,11 @@ extern const gpio_cfg_t DEV_DC_PIN;
 /**
  * SPI
 **/
-void lcd_write(uint8_t* data, int size, lcd_write_cb_t wr_callback);
+void lcd_write(uint8_t* data, int size);
+void lcd_write_async(uint8_t* data, int size, lcd_write_cb_t wr_callback);
 void display_set_reset_pin(uint8_t state);
-#define DEV_SPI_WRITE(_dat) lcd_write(&_dat, 1, NULL)
+void lcd_irq_init(void);
+#define DEV_SPI_WRITE(_dat) lcd_write(&_dat, 1)
 #define DEV_RESET_LOW() display_set_reset_pin(0)
 #define DEV_RESET_HIGH() display_set_reset_pin(1)
 /**
diff --git a/lib/gfx/LCD/LCD_Driver.c b/lib/gfx/LCD/LCD_Driver.c
index a75582d3..a6c50e5a 100644
--- a/lib/gfx/LCD/LCD_Driver.c
+++ b/lib/gfx/LCD/LCD_Driver.c
@@ -29,11 +29,6 @@
 ******************************************************************************/
 #include "LCD_Driver.h"
 
-typedef union {
-    uint8_t fb[LCD_HEIGHT][LCD_WIDTH][2];
-    uint8_t raw[LCD_HEIGHT * LCD_WIDTH * 2];
-} frame_t;
-
 static frame_t frames[2];
 static uint8_t active_frame;
 static uint8_t update_in_progress;
@@ -328,7 +323,7 @@ static void LCD_Set(uint8_t *data, int len)
 	LCD_SetCursor(0, 0, 160 - 1, 80 - 1);
 	DEV_Digital_Write(DEV_DC_PIN, 1);
     update_in_progress = 1;
-    lcd_write(data, len, update_cb);
+    lcd_write_async(data, len, update_cb);
 }
 
 int LCD_Update(void)
@@ -341,3 +336,6 @@ int LCD_Update(void)
     return 0;
 }
 
+frame_t *LCD_Framebuffer(void) {
+	return frame();
+}
diff --git a/lib/gfx/LCD/LCD_Driver.h b/lib/gfx/LCD/LCD_Driver.h
index 6e4f3ed9..aff3b575 100644
--- a/lib/gfx/LCD/LCD_Driver.h
+++ b/lib/gfx/LCD/LCD_Driver.h
@@ -35,6 +35,10 @@
 #define LCD_WIDTH   160 //LCD width
 #define LCD_HEIGHT  80 //LCD height
 
+typedef union {
+    uint8_t fb[LCD_HEIGHT][LCD_WIDTH][2];
+    uint8_t raw[LCD_HEIGHT * LCD_WIDTH * 2];
+} frame_t;
 
 void LCD_WriteData_Byte(UBYTE da); 
 void LCD_WriteData_Word(UWORD da);
@@ -52,5 +56,6 @@ void LCD_ClearWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD U
  *                1 - an update was already in progress
  */
 int LCD_Update(void);
+frame_t *LCD_Framebuffer(void);
 
 #endif
-- 
GitLab