|  | @@ -15,15 +15,6 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "ssd13x6.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#define COM_Disable_LR_Remap 0
 | 
	
		
			
				|  |  | -#define COM_Enable_LR_Remap BIT( 5 )
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#define COM_Pins_Sequential 0
 | 
	
		
			
				|  |  | -#define COM_Pins_Alternative BIT( 4 )
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#define COM_ScanDir_LR 0
 | 
	
		
			
				|  |  | -#define COM_ScanDir_RL 1
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // used by both but different
 | 
	
		
			
				|  |  |  static uint8_t SSDCmd_Set_Display_Start_Line;
 | 
	
		
			
				|  |  |  static uint8_t SSDCmd_Set_Display_Offset;
 | 
	
	
		
			
				|  | @@ -37,6 +28,11 @@ static const uint8_t SSD13x6_Max_Row = 7;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int Height );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +int  SSD13x6_GetCaps( struct SSD13x6_Device* DeviceHandle ) {
 | 
	
		
			
				|  |  | +	if (DeviceHandle->Model == SH1106) return 0;
 | 
	
		
			
				|  |  | +	else return CAPS_COLUMN_RANGE | CAPS_PAGE_RANGE	| CAPS_ADDRESS_VERTICAL;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  bool SSD13x6_WriteCommand( struct SSD13x6_Device* DeviceHandle, SSDCmd SSDCommand ) {
 | 
	
		
			
				|  |  |      NullCheck( DeviceHandle->WriteCommand, return false );
 | 
	
		
			
				|  |  |      return ( DeviceHandle->WriteCommand ) ( DeviceHandle, SSDCommand );
 | 
	
	
		
			
				|  | @@ -100,6 +96,9 @@ void SSD132x_ReMap( struct SSD13x6_Device* DeviceHandle ) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SSD13x6_SetDisplayAddressMode( struct SSD13x6_Device* DeviceHandle, SSD13x6_AddressMode AddressMode ) {
 | 
	
		
			
				|  |  |  	switch (DeviceHandle->Model) {
 | 
	
		
			
				|  |  | +	case SH1106:
 | 
	
		
			
				|  |  | +		// does not exist on SH1106
 | 
	
		
			
				|  |  | +		break;
 | 
	
		
			
				|  |  |  	case SSD1306:
 | 
	
		
			
				|  |  |  		SSD13x6_WriteCommand( DeviceHandle, 0x20 );
 | 
	
		
			
				|  |  |  		SSD13x6_WriteCommand( DeviceHandle, AddressMode );
 | 
	
	
		
			
				|  | @@ -112,9 +111,19 @@ void SSD13x6_SetDisplayAddressMode( struct SSD13x6_Device* DeviceHandle, SSD13x6
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle ) {
 | 
	
		
			
				|  |  | -	SSD13x6_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1);
 | 
	
		
			
				|  |  | -	SSD13x6_SetPageAddress( DeviceHandle, 0, DeviceHandle->Height / 8 - 1);
 | 
	
		
			
				|  |  | -    SSD13x6_WriteData( DeviceHandle, DeviceHandle->Framebuffer, DeviceHandle->FramebufferSize );
 | 
	
		
			
				|  |  | +	if (DeviceHandle->Model == SH1106) {
 | 
	
		
			
				|  |  | +		// SH1106 requires a page-by-page update and ahs no end Page/Column
 | 
	
		
			
				|  |  | +		for (int i = 0; i < DeviceHandle->Height / 8 ; i++) {
 | 
	
		
			
				|  |  | +			SSD13x6_SetPageAddress( DeviceHandle, i, 0);
 | 
	
		
			
				|  |  | +			SSD13x6_SetColumnAddress( DeviceHandle, 0, 0);			
 | 
	
		
			
				|  |  | +			SSD13x6_WriteData( DeviceHandle, DeviceHandle->Framebuffer + i*DeviceHandle->Width, DeviceHandle->Width );
 | 
	
		
			
				|  |  | +		}	
 | 
	
		
			
				|  |  | +	} else {	
 | 
	
		
			
				|  |  | +		// others have an automatic counter and end Page/Column
 | 
	
		
			
				|  |  | +		SSD13x6_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1);
 | 
	
		
			
				|  |  | +		SSD13x6_SetPageAddress( DeviceHandle, 0, DeviceHandle->Height / 8 - 1);
 | 
	
		
			
				|  |  | +		SSD13x6_WriteData( DeviceHandle, DeviceHandle->Framebuffer, DeviceHandle->FramebufferSize );
 | 
	
		
			
				|  |  | +	}	
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) {
 | 
	
	
		
			
				|  | @@ -125,6 +134,7 @@ void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, s
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SSD13x6_SetHFlip( struct SSD13x6_Device* DeviceHandle, bool On ) {
 | 
	
		
			
				|  |  |  	switch (DeviceHandle->Model) {
 | 
	
		
			
				|  |  | +	case SH1106:		
 | 
	
		
			
				|  |  |  	case SSD1306:	
 | 
	
		
			
				|  |  |  		SSD13x6_WriteCommand( DeviceHandle, On ? 0xA1 : 0xA0 );
 | 
	
		
			
				|  |  |  		break;
 | 
	
	
		
			
				|  | @@ -137,6 +147,7 @@ void SSD13x6_SetHFlip( struct SSD13x6_Device* DeviceHandle, bool On ) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SSD13x6_SetVFlip( struct SSD13x6_Device* DeviceHandle, bool On ) {
 | 
	
		
			
				|  |  |  	switch (DeviceHandle->Model) {
 | 
	
		
			
				|  |  | +	case SH1106:	
 | 
	
		
			
				|  |  |  	case SSD1306:	
 | 
	
		
			
				|  |  |  		SSD13x6_WriteCommand( DeviceHandle, On ? 0xC8 : 0xC0 );
 | 
	
		
			
				|  |  |  		break;
 | 
	
	
		
			
				|  | @@ -150,10 +161,18 @@ void SSD13x6_SetVFlip( struct SSD13x6_Device* DeviceHandle, bool On ) {
 | 
	
		
			
				|  |  |  void SSD13x6_SetColumnAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End ) {
 | 
	
		
			
				|  |  |      CheckBounds( Start > SSD13x6_Max_Col, return );
 | 
	
		
			
				|  |  |      CheckBounds( End > SSD13x6_Max_Col, return );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Column_Address );
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, Start );
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, End );
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	// on SH1106, there is no "end column"
 | 
	
		
			
				|  |  | +	if (DeviceHandle->Model == SH1106) {
 | 
	
		
			
				|  |  | +		// well, unfortunately this driver is 132 colums but most displays are 128...
 | 
	
		
			
				|  |  | +		if (DeviceHandle->Width != 132) Start += 2;
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, 0x10 | (Start >> 4) );
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, 0x00 | (Start & 0x0f) );
 | 
	
		
			
				|  |  | +	} else {	
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Column_Address );
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, Start );
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, End );
 | 
	
		
			
				|  |  | +	}	
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SSD13x6_SetPageAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End ) {
 | 
	
	
		
			
				|  | @@ -162,15 +181,20 @@ void SSD13x6_SetPageAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start,
 | 
	
		
			
				|  |  |      CheckBounds( Start > SSD13x6_Max_Row, return );
 | 
	
		
			
				|  |  |      CheckBounds( End > SSD13x6_Max_Row, return );
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  | -	// in case of SSD1326, this is sub-optimal as it can address by line, not by page
 | 
	
		
			
				|  |  | -	if (DeviceHandle->Model != SSD1306) {
 | 
	
		
			
				|  |  | -		Start *= 8;
 | 
	
		
			
				|  |  | -		End = (End + 1) * 8 - 1;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	// on SH1106, there is no "end page"
 | 
	
		
			
				|  |  | +	if (DeviceHandle->Model == SH1106) {
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0xB0 | Start );			
 | 
	
		
			
				|  |  | +	} else {	
 | 
	
		
			
				|  |  | +		// in case of SSD1326, this is sub-optimal as it can address by line, not by page
 | 
	
		
			
				|  |  | +		if (DeviceHandle->Model != SSD1306) {
 | 
	
		
			
				|  |  | +			Start *= 8;
 | 
	
		
			
				|  |  | +			End = (End + 1) * 8 - 1;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  | -	SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Page_Address );	
 | 
	
		
			
				|  |  | -	SSD13x6_WriteCommand( DeviceHandle, Start );
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, End );
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Page_Address );	
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, Start );
 | 
	
		
			
				|  |  | +		SSD13x6_WriteCommand( DeviceHandle, End );
 | 
	
		
			
				|  |  | +	}	
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool SSD13x6_HWReset( struct SSD13x6_Device* DeviceHandle ) {
 | 
	
	
		
			
				|  | @@ -186,50 +210,40 @@ bool SSD13x6_HWReset( struct SSD13x6_Device* DeviceHandle ) {
 | 
	
		
			
				|  |  |      return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/*
 | 
	
		
			
				|  |  | - * This is all a big giant mystery that I have yet to figure out.
 | 
	
		
			
				|  |  | - * Beware all ye who enter.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -static void SetCOMPinConfiguration( struct SSD13x6_Device* DeviceHandle, uint32_t RemapCFG, uint32_t PinCFG, int ScanDir ) {
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, 0xDA );
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, ( uint8_t ) ( RemapCFG | PinCFG | BIT( 1 ) ) );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    SSD13x6_WriteCommand( DeviceHandle, 
 | 
	
		
			
				|  |  | -        ( ScanDir == COM_ScanDir_LR ) ? 0xC0 : 0xC8
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int Height ) {
 | 
	
		
			
				|  |  |      DeviceHandle->Width = Width;
 | 
	
		
			
				|  |  |      DeviceHandle->Height = Height;
 | 
	
		
			
				|  |  | -    DeviceHandle->FramebufferSize = ( DeviceHandle->Width * Height ) / 8;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // DeviceHandle->Framebuffer = heap_caps_calloc( 1, DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL );
 | 
	
		
			
				|  |  | -	DeviceHandle->Framebuffer = calloc( 1, DeviceHandle->FramebufferSize );
 | 
	
		
			
				|  |  | -    NullCheck( DeviceHandle->Framebuffer, return false );
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  |  	SSD13x6_HWReset( DeviceHandle );
 | 
	
		
			
				|  |  | -	
 | 
	
		
			
				|  |  | -	if (DeviceHandle->Model == SSD1306) {
 | 
	
		
			
				|  |  | +	SSD13x6_DisplayOff( DeviceHandle );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (DeviceHandle->Model == SSD1306 || DeviceHandle->Model == SH1106) {
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Display_Start_Line = 0x40;
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Display_Offset = 0xD3;
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Column_Address = 0x21,
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Display_CLK = 0xD5;
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Page_Address = 0x22;		
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  |  		SSD13x6_Max_Col = 127;
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  | -		// charge pump regulator, do direct init
 | 
	
		
			
				|  |  | -		SSD13x6_WriteCommand( DeviceHandle, 0x8D );
 | 
	
		
			
				|  |  | -		SSD13x6_WriteCommand( DeviceHandle, 0x14 ); /* MAGIC NUMBER */
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  | -		if ( Height == 64 ) {
 | 
	
		
			
				|  |  | -			SetCOMPinConfiguration( DeviceHandle, COM_Disable_LR_Remap, COM_Pins_Alternative, COM_ScanDir_LR );
 | 
	
		
			
				|  |  | +		if (DeviceHandle->Model == SSD1306) {
 | 
	
		
			
				|  |  | +			// charge pump regulator, do direct init
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0x8D );
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0x14 ); 
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  | +			// COM pins HW config (alternative:EN, remap:DIS) - some display might need something difference
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0xDA );
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, (1 << 4) | (0 < 5) );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		} else {
 | 
	
		
			
				|  |  | -			SetCOMPinConfiguration( DeviceHandle, COM_Disable_LR_Remap, COM_Pins_Sequential, COM_ScanDir_LR );
 | 
	
		
			
				|  |  | +			// charge pump regulator, do direct init
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0xAD );
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0x8B ); 
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  | +			// COM pins HW config (alternative:EN) - some display might need something difference
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 0xDA );
 | 
	
		
			
				|  |  | +			SSD13x6_WriteCommand( DeviceHandle, 1 << 4);
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	} else if (DeviceHandle->Model == SSD1326) {
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Display_Start_Line = 0xA1;
 | 
	
		
			
				|  |  |  		SSDCmd_Set_Display_Offset = 0xA2;
 | 
	
	
		
			
				|  | @@ -245,21 +259,23 @@ static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int He
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  |  		SSD13x6_SetHFlip( DeviceHandle, false );
 | 
	
		
			
				|  |  |  		SSD13x6_SetVFlip( DeviceHandle, false );
 | 
	
		
			
				|  |  | -	}	
 | 
	
		
			
				|  |  | -	
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	SSD13x6_SetMuxRatio( DeviceHandle, Height - 1 );
 | 
	
		
			
				|  |  |      SSD13x6_SetDisplayOffset( DeviceHandle, 0x00 );
 | 
	
		
			
				|  |  | -    SSD13x6_SetDisplayStartLine( DeviceHandle, 0 );
 | 
	
		
			
				|  |  | +	SSD13x6_SetDisplayStartLine( DeviceHandle, 0 );
 | 
	
		
			
				|  |  |  	SSD13x6_SetContrast( DeviceHandle, 0x7F );
 | 
	
		
			
				|  |  |      SSD13x6_DisableDisplayRAM( DeviceHandle );
 | 
	
		
			
				|  |  | +	SSD13x6_SetVFlip( DeviceHandle, false );
 | 
	
		
			
				|  |  | +	SSD13x6_SetHFlip( DeviceHandle, false );
 | 
	
		
			
				|  |  |  	SSD13x6_SetInverted( DeviceHandle, false );
 | 
	
		
			
				|  |  |      SSD13x6_SetDisplayClocks( DeviceHandle, 0, 8 );
 | 
	
		
			
				|  |  | -	SSD13x6_SetDisplayAddressMode( DeviceHandle, AddressMode_Vertical );
 | 
	
		
			
				|  |  | +	SSD13x6_SetDisplayAddressMode( DeviceHandle, AddressMode_Horizontal );
 | 
	
		
			
				|  |  |      SSD13x6_SetColumnAddress( DeviceHandle, 0, DeviceHandle->Width - 1 );
 | 
	
		
			
				|  |  |      SSD13x6_SetPageAddress( DeviceHandle, 0, ( DeviceHandle->Height / 8 ) - 1 );
 | 
	
		
			
				|  |  |  	SSD13x6_EnableDisplayRAM( DeviceHandle );
 | 
	
		
			
				|  |  |      SSD13x6_DisplayOn( DeviceHandle );
 | 
	
		
			
				|  |  | -    SSD13x6_Update( DeviceHandle );
 | 
	
		
			
				|  |  | +	SSD13x6_Update( DeviceHandle );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return true;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -269,13 +285,15 @@ bool SSD13x6_Init_I2C( struct SSD13x6_Device* DeviceHandle, int Width, int Heigh
 | 
	
		
			
				|  |  |      NullCheck( WriteCommand, return false );
 | 
	
		
			
				|  |  |      NullCheck( WriteData, return false );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    memset( DeviceHandle, 0, sizeof( struct SSD13x6_Device ) );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      DeviceHandle->WriteCommand = WriteCommand;
 | 
	
		
			
				|  |  |      DeviceHandle->WriteData = WriteData;
 | 
	
		
			
				|  |  |      DeviceHandle->Reset = Reset;
 | 
	
		
			
				|  |  |      DeviceHandle->Address = I2CAddress;
 | 
	
		
			
				|  |  |      DeviceHandle->RSTPin = ResetPin;
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  | +	DeviceHandle->FramebufferSize = ( Width * Height ) / 8;
 | 
	
		
			
				|  |  | +	DeviceHandle->Framebuffer = calloc( 1, DeviceHandle->FramebufferSize );
 | 
	
		
			
				|  |  | +    NullCheck( DeviceHandle->Framebuffer, return false );
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  |      return SSD13x6_Init( DeviceHandle, Width, Height );
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -285,8 +303,6 @@ bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Heigh
 | 
	
		
			
				|  |  |      NullCheck( WriteCommand, return false );
 | 
	
		
			
				|  |  |      NullCheck( WriteData, return false );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    memset( DeviceHandle, 0, sizeof( struct SSD13x6_Device ) );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      DeviceHandle->WriteCommand = WriteCommand;
 | 
	
		
			
				|  |  |      DeviceHandle->WriteData = WriteData;
 | 
	
		
			
				|  |  |      DeviceHandle->Reset = Reset;
 | 
	
	
		
			
				|  | @@ -294,5 +310,9 @@ bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Heigh
 | 
	
		
			
				|  |  |      DeviceHandle->RSTPin = ResetPin;
 | 
	
		
			
				|  |  |      DeviceHandle->CSPin = CSPin;
 | 
	
		
			
				|  |  |  	
 | 
	
		
			
				|  |  | +	DeviceHandle->FramebufferSize = ( Width * Height ) / 8;
 | 
	
		
			
				|  |  | +    DeviceHandle->Framebuffer = heap_caps_calloc( 1, DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
 | 
	
		
			
				|  |  | +    NullCheck( DeviceHandle->Framebuffer, return false );
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  |      return SSD13x6_Init( DeviceHandle, Width, Height );
 | 
	
		
			
				|  |  |  }
 |