浏览代码

Display improvements

philippe44 5 年之前
父节点
当前提交
efa818e794

+ 7 - 18
components/display/SH1106.c

@@ -21,7 +21,7 @@
 
 static char TAG[] = "SH1106";
 
-struct SH1106_Private {
+struct PrivateSpace {
 	uint8_t *Shadowbuffer;
 };
 
@@ -40,7 +40,7 @@ static void SetPageAddress( struct GDS_Device* Device, uint8_t Start, uint8_t En
 
 static void Update( struct GDS_Device* Device ) {
 #ifdef SHADOW_BUFFER
-	struct SH1106_Private *Private = (struct SH1106_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 	// not sure the compiler does not have to redo all calculation in for loops, so local it is
 	int width = Device->Width, rows = Device->Height / 8;
 	uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer;
@@ -84,27 +84,15 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
 }
 
 static bool Init( struct GDS_Device* Device ) {
-	Device->FramebufferSize = ( Device->Width * Device->Height ) / 8;	
-	
-// benchmarks showed little gain to have SPI memory already in IRAL vs letting driver copy		
 #ifdef SHADOW_BUFFER	
-	struct SH1106_Private *Private = (struct SH1106_Private*) Device->Private;
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
-    NullCheck( Device->Framebuffer, return false );
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 #ifdef USE_IRAM
-	if (Device->IF == IF_SPI) Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
+	if (Device->IF == GDS_IF_SPI) Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
 	else 
 #endif
 	Private->Shadowbuffer = malloc( Device->FramebufferSize );	
 	NullCheck( Private->Shadowbuffer, return false );
 	memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize);
-#else	// not SHADOW_BUFFER
-#ifdef USE_IRAM
-	// benchmarks showed little gain to have SPI memory already in IRAL vs letting driver copy
-	if (Device->IF == IF_SPI) Device->Framebuffer = heap_caps_calloc( 1, Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
-	else 
-#endif
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
 #endif	
 		
 	// need to be off and disable display RAM
@@ -149,8 +137,6 @@ static const struct GDS_Device SH1106 = {
 	.DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast,
 	.SetVFlip = SetVFlip, .SetHFlip = SetHFlip,
 	.Update = Update, .Init = Init,
-	//.DrawPixelFast = GDS_DrawPixelFast,
-	//.ClearWindow = ClearWindow,
 };	
 
 struct GDS_Device* SH1106_Detect(char *Driver, struct GDS_Device* Device) {
@@ -159,6 +145,9 @@ struct GDS_Device* SH1106_Detect(char *Driver, struct GDS_Device* Device) {
 	if (!Device) Device = calloc(1, sizeof(struct GDS_Device));
 	*Device = SH1106;	
 	Device->Depth = 1;
+#if !defined SHADOW_BUFFER && defined USE_IRAM	
+	Device->Alloc = GDS_ALLOC_IRAM_SPI;
+#endif	
 	ESP_LOGI(TAG, "SH1106 driver");
 	
 	return Device;

+ 7 - 18
components/display/SSD1306.c

@@ -21,7 +21,7 @@
 
 static char TAG[] = "SSD1306";
 
-struct SSD1306_Private {
+struct PrivateSpace {
 	uint8_t *Shadowbuffer;
 };
 
@@ -40,7 +40,7 @@ static void SetPageAddress( struct GDS_Device* Device, uint8_t Start, uint8_t En
 
 static void Update( struct GDS_Device* Device ) {
 #ifdef SHADOW_BUFFER
-	struct SSD1306_Private *Private = (struct SSD1306_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 	// not sure the compiler does not have to redo all calculation in for loops, so local it is
 	int width = Device->Width, rows = Device->Height / 8;
 	uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer;
@@ -96,27 +96,15 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
 }
 
 static bool Init( struct GDS_Device* Device ) {
-	Device->FramebufferSize = ( Device->Width * Device->Height ) / 8;	
-	
-	// benchmarks showed little gain to have SPI memory already in IRAL vs letting driver copy		
 #ifdef SHADOW_BUFFER	
-	struct SSD1306_Private *Private = (struct SSD1306_Private*) Device->Private;
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
-    NullCheck( Device->Framebuffer, return false );
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 #ifdef USE_IRAM
-	if (Device->IF == IF_SPI) Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
+	if (Device->IF == GDS_IF_SPI) Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
 	else 
 #endif
 	Private->Shadowbuffer = malloc( Device->FramebufferSize );	
 	NullCheck( Private->Shadowbuffer, return false );
 	memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize);
-#else	// not SHADOW_BUFFER
-#ifdef USE_IRAM
-	// benchmarks showed little gain to have SPI memory already in IRAL vs letting driver copy
-	if (Device->IF == IF_SPI) Device->Framebuffer = heap_caps_calloc( 1, Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
-	else 
-#endif
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
 #endif	
 		
 	// need to be off and disable display RAM
@@ -164,8 +152,6 @@ static const struct GDS_Device SSD1306 = {
 	.DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast,
 	.SetVFlip = SetVFlip, .SetHFlip = SetHFlip,
 	.Update = Update, .Init = Init,
-	//.DrawPixelFast = GDS_DrawPixelFast,
-	//.ClearWindow = ClearWindow,
 };	
 
 struct GDS_Device* SSD1306_Detect(char *Driver, struct GDS_Device* Device) {
@@ -174,6 +160,9 @@ struct GDS_Device* SSD1306_Detect(char *Driver, struct GDS_Device* Device) {
 	if (!Device) Device = calloc(1, sizeof(struct GDS_Device));
 	*Device = SSD1306;	
 	Device->Depth = 1;
+#if !defined SHADOW_BUFFER && defined USE_IRAM	
+	Device->Alloc = GDS_ALLOC_IRAM_SPI;
+#endif	
 	ESP_LOGI(TAG, "SSD1306 driver");
 	
 	return Device;

+ 18 - 33
components/display/SSD132x.c

@@ -26,7 +26,7 @@ static char TAG[] = "SSD132x";
 
 enum { SSD1326, SSD1327 };
 
-struct SSD132x_Private {
+struct PrivateSpace {
 	uint8_t *iRAM, *Shadowbuffer;
 	uint8_t ReMap, PageSize;
 	uint8_t Model;
@@ -67,7 +67,7 @@ static void SetRowAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End
 }
 
 static void Update4( struct GDS_Device* Device ) {
-	struct SSD132x_Private *Private = (struct SSD132x_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 		
 	// always update by full lines
 	SetColumnAddress( Device, 0, Device->Width / 2 - 1);
@@ -122,7 +122,7 @@ static void Update4( struct GDS_Device* Device ) {
 */ 
 static void Update1( struct GDS_Device* Device ) {
 #ifdef SHADOW_BUFFER
-	struct SSD132x_Private *Private = (struct SSD132x_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 	// not sure the compiler does not have to redo all calculation in for loops, so local it is
 	int width = Device->Width / 8, rows = Device->Height;
 	uint8_t *optr = Private->Shadowbuffer, *iptr = Device->Framebuffer;
@@ -198,7 +198,7 @@ static void DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, i
 }
 
 static void SetHFlip( struct GDS_Device* Device, bool On ) { 
-	struct SSD132x_Private *Private = (struct SSD132x_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 	if (Private->Model == SSD1326) Private->ReMap = On ? (Private->ReMap | ((1 << 0) | (1 << 2))) : (Private->ReMap & ~((1 << 0) | (1 << 2)));
 	else Private->ReMap = On ? (Private->ReMap | ((1 << 0) | (1 << 1))) : (Private->ReMap & ~((1 << 0) | (1 << 1)));
 	Device->WriteCommand( Device, 0xA0 );
@@ -206,7 +206,7 @@ static void SetHFlip( struct GDS_Device* Device, bool On ) {
 }	
 
 static void SetVFlip( struct GDS_Device *Device, bool On ) { 
-	struct SSD132x_Private *Private = (struct SSD132x_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 	if (Private->Model == SSD1326) Private->ReMap = On ? (Private->ReMap | (1 << 1)) : (Private->ReMap & ~(1 << 1));
 	else Private->ReMap = On ? (Private->ReMap | (1 << 4)) : (Private->ReMap & ~(1 << 4));
 	Device->WriteCommand( Device, 0xA0 );
@@ -222,26 +222,15 @@ static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) {
 }
 
 static bool Init( struct GDS_Device* Device ) {
-	struct SSD132x_Private *Private = (struct SSD132x_Private*) Device->Private;
+	struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
 	
 	// find a page size that is not too small is an integer of height
 	Private->PageSize = min(8, PAGE_BLOCK / (Device->Width / 2));
 	Private->PageSize = Device->Height / (Device->Height / Private->PageSize) ;	
 	
-#ifdef USE_IRAM	
-	// let SPI driver allocate memory, it has not proven to be more efficient
-	if (Device->IF == IF_SPI) Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
-#endif	
-	Device->FramebufferSize = ( Device->Width * Device->Height ) / 2;	
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
-    NullCheck( Device->Framebuffer, return false );
-	
-// benchmarks showed little gain to have SPI memory already in IRAM vs letting driver copy		
 #ifdef SHADOW_BUFFER	
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
-    NullCheck( Device->Framebuffer, return false );
 #ifdef USE_IRAM
-	if (Device->IF == IF_SPI) {
+	if (Device->IF == GDS_IF_SPI) {
 		if (Device->Depth == 1) {
 			Private->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
 		} else {
@@ -252,20 +241,13 @@ static bool Init( struct GDS_Device* Device ) {
 #endif
 	Private->Shadowbuffer = malloc( Device->FramebufferSize );	
 	memset(Private->Shadowbuffer, 0xFF, Device->FramebufferSize);
-#else	// not SHADOW_BUFFER
-#ifdef USE_IRAM
-	if (Device->IF == IF_SPI) {
-		if (Device->Depth == 1) {
-			Device->Framebuffer = heap_caps_calloc( 1, Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
-		} else  {
-			Device->Framebuffer = calloc( 1, Device->FramebufferSize );	
-			Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
-		}
-	} else 
-#endif	
-	Device->Framebuffer = calloc( 1, Device->FramebufferSize );
+#else
+#ifdef USE_IRAM	
+	if (Device->Depth == 4 && Device->IF == GDS_IF_SPI) Private->iRAM = heap_caps_malloc( Private->PageSize * Device->Width / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
 #endif	
 
+#endif
+
 	ESP_LOGI(TAG, "SSD1326/7 with bit depth %u, page %u, iRAM %p", Device->Depth, Private->PageSize, Private->iRAM);
 			
 	// need to be off and disable display RAM
@@ -317,14 +299,14 @@ static const struct GDS_Device SSD132x = {
 struct GDS_Device* SSD132x_Detect(char *Driver, struct GDS_Device* Device) {
 	uint8_t Model;
 	
-	if (!strcasestr(Driver, "SSD1326")) Model = SSD1326;
-	else if (!strcasestr(Driver, "SSD1327")) Model = SSD1327;
+	if (strcasestr(Driver, "SSD1326")) Model = SSD1326;
+	else if (strcasestr(Driver, "SSD1327")) Model = SSD1327;
 	else return NULL;
 	
 	if (!Device) Device = calloc(1, sizeof(struct GDS_Device));
 	
 	*Device = SSD132x;	
-	((struct SSD132x_Private*) Device->Private)->Model = Model;
+	((struct PrivateSpace*) Device->Private)->Model = Model;
 	
 	sscanf(Driver, "%*[^:]:%c", &Device->Depth);
 	
@@ -333,6 +315,9 @@ struct GDS_Device* SSD132x_Detect(char *Driver, struct GDS_Device* Device) {
 		Device->DrawPixelFast = DrawPixel1Fast;
 		Device->DrawBitmapCBR = DrawBitmapCBR;
 		Device->ClearWindow = ClearWindow;
+#if !defined SHADOW_BUFFER && defined USE_IRAM	
+		Device->Alloc = GDS_ALLOC_IRAM_SPI;
+#endif	
 	} else {
 		Device->Depth = 4;
 	}	

+ 17 - 5
components/display/core/gds.c

@@ -132,10 +132,22 @@ bool GDS_Reset( struct GDS_Device* Device ) {
     return true;
 }
 
-void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { Device->SetContrast( Device, Contrast); }
-void GDS_SetHFlip( struct GDS_Device* Device, bool On ) { Device->SetHFlip( Device, On ); }
-void GDS_SetVFlip( struct GDS_Device* Device, bool On ) { Device->SetVFlip( Device, On ); }
+bool GDS_Init( struct GDS_Device* Device ) {
+	Device->FramebufferSize = ( Device->Width * Device->Height ) / (8  / Device->Depth);
+	
+	if ((Device->Alloc && GDS_ALLOC_IRAM) || ((Device->Alloc & GDS_ALLOC_IRAM_SPI) && Device->IF == GDS_IF_SPI)) heap_caps_calloc( 1, Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
+	else Device->Framebuffer = calloc( 1, Device->FramebufferSize );
+	NullCheck( Device->Framebuffer, return false );
+	
+	bool Res = Device->Init( Device );
+	if (!Res) free(Device->Framebuffer);
+	return Res;
+}
+
+void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { if (Device->SetContrast) Device->SetContrast( Device, Contrast); }
+void GDS_SetHFlip( struct GDS_Device* Device, bool On ) { if (Device->SetHFlip) Device->SetHFlip( Device, On ); }
+void GDS_SetVFlip( struct GDS_Device* Device, bool On ) { if (Device->SetVFlip) Device->SetVFlip( Device, On ); }
 int	GDS_GetWidth( struct GDS_Device* Device ) { return Device->Width; }
 int	GDS_GetHeight( struct GDS_Device* Device ) { return Device->Height; }
-void GDS_DisplayOn( struct GDS_Device* Device ) { Device->DisplayOn( Device ); }
-void GDS_DisplayOff( struct GDS_Device* Device ) { Device->DisplayOff( Device ); }
+void GDS_DisplayOn( struct GDS_Device* Device ) { if (Device->DisplayOn) Device->DisplayOn( Device ); }
+void GDS_DisplayOff( struct GDS_Device* Device ) { if (Device->DisplayOff) Device->DisplayOff( Device ); }

+ 1 - 1
components/display/core/gds.h

@@ -19,7 +19,7 @@ enum { 	GDS_COLOR_L0 = 0, GDS_COLOR_L1 = 1, GDS_COLOR_L2, GDS_COLOR_L3, GDS_COLO
 };
 		
 #define GDS_COLOR_BLACK GDS_COLOR_L0
-#define GDS_COLOR_WHITE GDS_COLOR_L1
+#define GDS_COLOR_WHITE (GDS_COLOR_MAX - 1)
 #define GDS_COLOR_XOR 	(GDS_COLOR_MAX + 1)
 
 struct GDS_Device;

+ 11 - 5
components/display/core/gds_private.h

@@ -7,6 +7,9 @@
 #include "gds.h"
 #include "gds_err.h"
 
+#define GDS_ALLOC_IRAM		0x01
+#define GDS_ALLOC_IRAM_SPI	0x02
+
 #define GDS_CLIPDEBUG_NONE 0
 #define GDS_CLIPDEBUG_WARNING 1
 #define GDS_CLIPDEBUG_ERROR 2
@@ -55,8 +58,8 @@ typedef bool ( *WriteDataProc ) ( struct GDS_Device* Device, const uint8_t* Data
 struct spi_device_t;
 typedef struct spi_device_t* spi_device_handle_t;
 
-#define IF_SPI	0
-#define IF_I2C	1
+#define GDS_IF_SPI	0
+#define GDS_IF_I2C	1
 
 struct GDS_Device {
 	uint8_t IF;
@@ -82,7 +85,8 @@ struct GDS_Device {
 	uint16_t Width;
     uint16_t Height;
 	uint8_t Depth;
-		
+	
+	uint8_t	Alloc;	
 	uint8_t* Framebuffer;
     uint16_t FramebufferSize;
 	bool Dirty;
@@ -95,12 +99,13 @@ struct GDS_Device {
 	// various driver-specific method
 	// must always provide 
 	bool (*Init)( struct GDS_Device* Device);
+	void (*Update)( struct GDS_Device* Device );
+	// may provide if supported
 	void (*SetContrast)( struct GDS_Device* Device, uint8_t Contrast );
 	void (*DisplayOn)( struct GDS_Device* Device );
 	void (*DisplayOff)( struct GDS_Device* Device );
 	void (*SetHFlip)( struct GDS_Device* Device, bool On );
 	void (*SetVFlip)( struct GDS_Device* Device, bool On );
-	void (*Update)( struct GDS_Device* Device );
 	// must provide for depth other than 1 (vertical) and 4 (may provide for optimization)
 	void (*DrawPixelFast)( struct GDS_Device* Device, int X, int Y, int Color );
 	void (*DrawBitmapCBR)(struct GDS_Device* Device, uint8_t *Data, int Width, int Height, int Color );
@@ -117,6 +122,7 @@ struct GDS_Device {
 };
 
 bool GDS_Reset( struct GDS_Device* Device );
+bool GDS_Init( struct GDS_Device* Device );
 
 inline bool IsPixelVisible( struct GDS_Device* Device, int x, int y )  {
     bool Result = (
@@ -152,7 +158,7 @@ inline void IRAM_ATTR GDS_DrawPixel1Fast( struct GDS_Device* Device, int X, int
     if ( Color == GDS_COLOR_XOR ) {
         *FBOffset ^= BIT( YBit );
     } else {
-        *FBOffset = ( Color == GDS_COLOR_WHITE ) ? *FBOffset | BIT( YBit ) : *FBOffset & ~BIT( YBit );
+        *FBOffset = ( Color >= GDS_COLOR_WHITE / 2 ) ? *FBOffset | BIT( YBit ) : *FBOffset & ~BIT( YBit );
     }
 }
 

+ 2 - 2
components/display/core/ifaces/default_if_i2c.c

@@ -73,7 +73,7 @@ bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int
     Device->WriteData = I2CDefaultWriteData;
     Device->Address = I2CAddress;
     Device->RSTPin = RSTPin;
-	Device->IF = IF_I2C;
+	Device->IF = GDS_IF_I2C;
 	Device->Width = Width;
 	Device->Height = Height;
 	
@@ -83,7 +83,7 @@ bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int
 		GDS_Reset( Device );
     }
 	
-    return Device->Init( Device );
+    return GDS_Init( Device );
 }
 
 static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength ) {

+ 2 - 2
components/display/core/ifaces/default_if_spi.c

@@ -58,7 +58,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
     Device->SPIHandle = SPIDevice;
     Device->RSTPin = RSTPin;
     Device->CSPin = CSPin;
-	Device->IF = IF_SPI;
+	Device->IF = GDS_IF_SPI;
 	Device->Width = Width;
 	Device->Height = Height;
 	
@@ -68,7 +68,7 @@ bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int
 		GDS_Reset( Device );
     }
 	
-	return Device->Init( Device );
+	return GDS_Init( Device );
 }
 
 static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {

+ 2 - 2
components/display/display.c

@@ -59,8 +59,8 @@ static EXT_RAM_ATTR struct {
 static void displayer_task(void *args);
 
 struct GDS_Device *display;   
-extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect;
-GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, NULL };
+extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect, ELD_Detect;
+GDS_DetectFunc *drivers[] = { SH1106_Detect, SSD1306_Detect, SSD132x_Detect, ELD_Detect, NULL };
 
 /****************************************************************************************
  *