From a3d0b67670b4ce93807b509b39a2847e5a954d92 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Sat, 22 Feb 2020 16:09:25 -0800 Subject: [PATCH] display refactor --- components/display/SH1106.c | 145 ++++++ components/display/SSD1306.c | 146 ++++++ components/display/component.mk | 4 +- components/display/core/gds.c | 92 ++++ components/display/core/gds.h | 30 ++ components/display/core/gds_default_if.h | 20 + components/display/core/gds_draw.c | 321 +++++++++++++ components/display/core/gds_draw.h | 26 + .../ssd13x6_err.h => core/gds_err.h} | 12 +- .../ssd13x6_font.c => core/gds_font.c} | 109 ++--- components/display/core/gds_font.h | 91 ++++ components/display/core/gds_private.h | 130 +++++ components/display/core/gds_text.c | 195 ++++++++ components/display/core/gds_text.h | 45 ++ .../ifaces/default_if_i2c.c | 76 ++- .../display/core/ifaces/default_if_spi.c | 109 +++++ components/display/display.c | 103 ++-- components/display/display.h | 37 +- components/display/driver_SSD13x6.c | 446 ------------------ .../{tarablessd13x6 => }/fonts/LICENSE-apache | 0 .../fonts/LICENSE-liberation-mono | 0 .../fonts/font_droid_sans_fallback_11x13.c | 4 +- .../fonts/font_droid_sans_fallback_15x17.c | 4 +- .../fonts/font_droid_sans_fallback_24x28.c | 4 +- .../fonts/font_droid_sans_mono_13x24.c | 4 +- .../fonts/font_droid_sans_mono_16x31.c | 4 +- .../fonts/font_droid_sans_mono_7x13.c | 4 +- .../fonts/font_liberation_mono_13x21.c | 4 +- .../fonts/font_liberation_mono_17x30.c | 4 +- .../fonts/font_liberation_mono_9x15.c | 4 +- .../{tarablessd13x6 => }/fonts/font_line_1.c | 4 +- .../{tarablessd13x6 => }/fonts/font_line_2.c | 4 +- .../fonts/font_tarable7seg_16x32.c | 4 +- .../fonts/font_tarable7seg_32x64.c | 4 +- .../tarablessd13x6/ifaces/default_if_spi.c | 123 ----- components/display/tarablessd13x6/ssd13x6.c | 351 -------------- components/display/tarablessd13x6/ssd13x6.h | 99 ---- .../tarablessd13x6/ssd13x6_default_if.h | 18 - .../display/tarablessd13x6/ssd13x6_draw.c | 253 ---------- .../display/tarablessd13x6/ssd13x6_draw.h | 54 --- .../display/tarablessd13x6/ssd13x6_font.h | 91 ---- components/raop/raop.c | 6 +- components/squeezelite/display.c | 63 +-- 43 files changed, 1561 insertions(+), 1686 deletions(-) create mode 100644 components/display/SH1106.c create mode 100644 components/display/SSD1306.c create mode 100644 components/display/core/gds.c create mode 100644 components/display/core/gds.h create mode 100644 components/display/core/gds_default_if.h create mode 100644 components/display/core/gds_draw.c create mode 100644 components/display/core/gds_draw.h rename components/display/{tarablessd13x6/ssd13x6_err.h => core/gds_err.h} (81%) rename components/display/{tarablessd13x6/ssd13x6_font.c => core/gds_font.c} (58%) create mode 100644 components/display/core/gds_font.h create mode 100644 components/display/core/gds_private.h create mode 100644 components/display/core/gds_text.c create mode 100644 components/display/core/gds_text.h rename components/display/{tarablessd13x6 => core}/ifaces/default_if_i2c.c (58%) create mode 100644 components/display/core/ifaces/default_if_spi.c delete mode 100644 components/display/driver_SSD13x6.c rename components/display/{tarablessd13x6 => }/fonts/LICENSE-apache (100%) rename components/display/{tarablessd13x6 => }/fonts/LICENSE-liberation-mono (100%) rename components/display/{tarablessd13x6 => }/fonts/font_droid_sans_fallback_11x13.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_droid_sans_fallback_15x17.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_droid_sans_fallback_24x28.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_droid_sans_mono_13x24.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_droid_sans_mono_16x31.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_droid_sans_mono_7x13.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_liberation_mono_13x21.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_liberation_mono_17x30.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_liberation_mono_9x15.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_line_1.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_line_2.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_tarable7seg_16x32.c (99%) rename components/display/{tarablessd13x6 => }/fonts/font_tarable7seg_32x64.c (99%) delete mode 100644 components/display/tarablessd13x6/ifaces/default_if_spi.c delete mode 100644 components/display/tarablessd13x6/ssd13x6.c delete mode 100644 components/display/tarablessd13x6/ssd13x6.h delete mode 100644 components/display/tarablessd13x6/ssd13x6_default_if.h delete mode 100644 components/display/tarablessd13x6/ssd13x6_draw.c delete mode 100644 components/display/tarablessd13x6/ssd13x6_draw.h delete mode 100644 components/display/tarablessd13x6/ssd13x6_font.h diff --git a/components/display/SH1106.c b/components/display/SH1106.c new file mode 100644 index 00000000..2847321d --- /dev/null +++ b/components/display/SH1106.c @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2017-2018 Tara Keeling + * 2020 Philippe G. + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include + +#include "gds.h" +#include "gds_private.h" + +#define SHADOW_BUFFER + +static char TAG[] = "SH1106"; + +// Functions are not declared to minimize # of lines + +static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { + // well, unfortunately this driver is 132 colums but most displays are 128... + if (Device->Width != 132) Start += 2; + Device->WriteCommand( Device, 0x10 | (Start >> 4) ); + Device->WriteCommand( Device, 0x00 | (Start & 0x0f) ); +} + +static void SetPageAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { + Device->WriteCommand( Device, 0xB0 | Start ); +} + +static void Update( struct GDS_Device* Device ) { +#ifdef SHADOW_BUFFER + // 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 = Device->Shadowbuffer, *iptr = Device->Framebuffer; + + // by row, find first and last columns that have been updated + for (int r = 0; r < rows; r++) { + uint8_t first = 0, last; + for (int c = 0; c < width; c++) { + if (*iptr != *optr) { + if (!first) first = c + 1; + last = c ; + } + *optr++ = *iptr++; + } + + // now update the display by "byte rows" + if (first--) { + SetColumnAddress( Device, first, last ); + SetPageAddress( Device, r, r); + Device->WriteData( Device, Device->Shadowbuffer + r*width + first, last - first + 1); + } + } +#else + // SH1106 requires a page-by-page update and has no end Page/Column + for (int i = 0; i < Device->Height / 8 ; i++) { + SH1106_SetPageAddress( Device, i, 0); + SH1106_SetColumnAddress( Device, 0, 0); + SH1106_WriteData( Device, Device->Framebuffer + i*Device->Width, Device->Width ); + } +#endif +} + +static void SetHFlip( struct GDS_Device* Device, bool On ) { Device->WriteCommand( Device, On ? 0xA1 : 0xA0 ); } +static void SetVFlip( struct GDS_Device *Device, bool On ) { Device->WriteCommand( Device, On ? 0xC8 : 0xC0 ); } +static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } +static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } + +static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { + Device->WriteCommand( Device, 0x81 ); + Device->WriteCommand( Device, Contrast ); +} + +static bool Init( struct GDS_Device* Device ) { + Device->FramebufferSize = ( Device->Width * Device->Height ) / 8; + Device->Framebuffer = calloc( 1, Device->FramebufferSize ); + NullCheck( Device->Framebuffer, return false ); + +#ifdef SHADOW_BUFFER + if (Device->IF == IF_I2C) Device->Shadowbuffer = malloc( Device->FramebufferSize ); + else Device->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); + NullCheck( Device->Shadowbuffer, return false ); + memset(Device->Shadowbuffer, 0xFF, Device->FramebufferSize); +#endif + + // need to be off and disable display RAM + Device->DisplayOff( Device ); + Device->WriteCommand( Device, 0xA5 ); + + // charge pump regulator, do direct init + Device->WriteCommand( Device, 0xAD ); + Device->WriteCommand( Device, 0x8B ); + + // COM pins HW config (alternative:EN) - some display might need something difference + Device->WriteCommand( Device, 0xDA ); + Device->WriteCommand( Device, 1 << 4); + + // MUX Ratio + Device->WriteCommand( Device, 0xA8 ); + Device->WriteCommand( Device, Device->Height - 1); + // Display Offset + Device->WriteCommand( Device, 0xD3 ); + Device->WriteCommand( Device, 0 ); + // Display Start Line + Device->WriteCommand( Device, 0x40 + 0x00 ); + Device->SetContrast( Device, 0x7F ); + // set flip modes + Device->SetVFlip( Device, false ); + Device->SetHFlip( Device, false ); + // no Display Inversion + Device->WriteCommand( Device, 0xA6 ); + // set Clocks + Device->WriteCommand( Device, 0xD5 ); + Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); + + // gone with the wind + Device->WriteCommand( Device, 0xA4 ); + Device->DisplayOn( Device ); + Device->Update( Device ); + + return true; +} + +static const struct GDS_Device SH1106 = { + .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, + .SetVFlip = SetVFlip, .SetHFlip = SetHFlip, + .DrawPixel = GDS_DrawPixel, .DrawPixelFast = GDS_DrawPixelFast, + .Update = Update, .Init = Init, +}; + +struct GDS_Device* SH1106_Detect(char *Driver, struct GDS_Device* Device) { + if (!strcasestr(Driver, "SH1106")) return NULL; + + if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); + *Device = SH1106; + ESP_LOGI(TAG, "SH1106 driver"); + + return Device; +} \ No newline at end of file diff --git a/components/display/SSD1306.c b/components/display/SSD1306.c new file mode 100644 index 00000000..adb34b1b --- /dev/null +++ b/components/display/SSD1306.c @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2017-2018 Tara Keeling + * 2020 Philippe G. + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include + +#include "gds.h" +#include "gds_private.h" + +#define SHADOW_BUFFER + +static char TAG[] = "SSD1306"; + +// Functions are not deckared to minimize # of lines + +static void SetColumnAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { + Device->WriteCommand( Device, 0x21 ); + Device->WriteCommand( Device, Start ); + Device->WriteCommand( Device, End ); +} +static void SetPageAddress( struct GDS_Device* Device, uint8_t Start, uint8_t End ) { + Device->WriteCommand( Device, 0x22 ); + Device->WriteCommand( Device, Start ); + Device->WriteCommand( Device, End ); +} + +static void Update( struct GDS_Device* Device ) { +#ifdef SHADOW_BUFFER + // 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 = Device->Shadowbuffer, *iptr = Device->Framebuffer; + + // by row, find first and last columns that have been updated + for (int r = 0; r < rows; r++) { + uint8_t first = 0, last; + for (int c = 0; c < width; c++) { + if (*iptr != *optr) { + if (!first) first = c + 1; + last = c ; + } + *optr++ = *iptr++; + } + + // now update the display by "byte rows" + if (first--) { + SetColumnAddress( Device, first, last ); + SetPageAddress( Device, r, r); + Device->WriteData( Device, Device->Shadowbuffer + r*width + first, last - first + 1); + } + } +#else + // automatic counter and end Page/Column + SetColumnAddress( Device, 0, Device->Width - 1); + SetPageAddress( Device, 0, Device->Height / 8 - 1); + Device->WriteData( Device, Device->Framebuffer, Device->FramebufferSize ); +#endif +} + +static void SetHFlip( struct GDS_Device* Device, bool On ) { Device->WriteCommand( Device, On ? 0xA1 : 0xA0 ); } +static void SetVFlip( struct GDS_Device *Device, bool On ) { Device->WriteCommand( Device, On ? 0xC8 : 0xC0 ); } +static void DisplayOn( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAF ); } +static void DisplayOff( struct GDS_Device* Device ) { Device->WriteCommand( Device, 0xAE ); } + +static void SetContrast( struct GDS_Device* Device, uint8_t Contrast ) { + Device->WriteCommand( Device, 0x81 ); + Device->WriteCommand( Device, Contrast ); +} + +static bool Init( struct GDS_Device* Device ) { + Device->FramebufferSize = ( Device->Width * Device->Height ) / 8; + Device->Framebuffer = calloc( 1, Device->FramebufferSize ); + NullCheck( Device->Framebuffer, return false ); + +#ifdef SHADOW_BUFFER + if (Device->IF == IF_I2C) Device->Shadowbuffer = malloc( Device->FramebufferSize ); + else Device->Shadowbuffer = heap_caps_malloc( Device->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); + NullCheck( Device->Shadowbuffer, return false ); + memset(Device->Shadowbuffer, 0xFF, Device->FramebufferSize); +#endif + + // need to be off and disable display RAM + Device->DisplayOff( Device ); + Device->WriteCommand( Device, 0xA5 ); + + // charge pump regulator, do direct init + Device->WriteCommand( Device, 0x8D ); + Device->WriteCommand( Device, 0x14 ); + + // COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something difference + Device->WriteCommand( Device, 0xDA ); + Device->WriteCommand( Device, ((Device->Height == 64 ? 1 : 0) << 4) | (0 < 5) ); + + // MUX Ratio + Device->WriteCommand( Device, 0xA8 ); + Device->WriteCommand( Device, Device->Height - 1); + // Display Offset + Device->WriteCommand( Device, 0xD3 ); + Device->WriteCommand( Device, 0 ); + // Display Start Line + Device->WriteCommand( Device, 0x40 + 0x00 ); + Device->SetContrast( Device, 0x7F ); + // set flip modes + Device->SetVFlip( Device, false ); + Device->SetHFlip( Device, false ); + // no Display Inversion + Device->WriteCommand( Device, 0xA6 ); + // set Clocks + Device->WriteCommand( Device, 0xD5 ); + Device->WriteCommand( Device, ( 0x08 << 4 ) | 0x00 ); + // set Adressing Mode Horizontal + Device->WriteCommand( Device, 0x20 ); + Device->WriteCommand( Device, 0 ); + + // gone with the wind + Device->WriteCommand( Device, 0xA4 ); + Device->DisplayOn( Device ); + Device->Update( Device ); + + return true; +} + +static const struct GDS_Device SSD1306 = { + .DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast, + .SetVFlip = SetVFlip, .SetHFlip = SetHFlip, + .DrawPixel = GDS_DrawPixel, .DrawPixelFast = GDS_DrawPixelFast, + .Update = Update, .Init = Init, +}; + +struct GDS_Device* SSD1306_Detect(char *Driver, struct GDS_Device* Device) { + if (!strcasestr(Driver, "SSD1306")) return NULL; + + if (!Device) Device = calloc(1, sizeof(struct GDS_Device)); + *Device = SSD1306; + ESP_LOGI(TAG, "SSD1306 driver"); + + return Device; +} \ No newline at end of file diff --git a/components/display/component.mk b/components/display/component.mk index 295c75c4..c26f89d8 100644 --- a/components/display/component.mk +++ b/components/display/component.mk @@ -7,6 +7,6 @@ # please read the SDK documents if you need to do this. # -COMPONENT_SRCDIRS := . tarablessd13x6 tarablessd13x6/fonts tarablessd13x6/ifaces +COMPONENT_SRCDIRS := . core core/ifaces fonts COMPONENT_ADD_INCLUDEDIRS := . -COMPONENT_ADD_INCLUDEDIRS += ./tarablessd13x6 \ No newline at end of file +COMPONENT_ADD_INCLUDEDIRS += ./core \ No newline at end of file diff --git a/components/display/core/gds.c b/components/display/core/gds.c new file mode 100644 index 00000000..db738d6a --- /dev/null +++ b/components/display/core/gds.c @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2017-2018 Tara Keeling + * 2020 Philippe G. + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_log.h" + +#include "gds.h" +#include "gds_private.h" + +static struct GDS_Device Display; + +static char TAG[] = "gds"; + +struct GDS_Device* GDS_AutoDetect( char *Driver, GDS_DetectFunc DetectFunc[] ) { + for (int i = 0; DetectFunc[i]; i++) { + if (DetectFunc[i](Driver, &Display)) { + ESP_LOGD(TAG, "Detected driver %p", &Display); + return &Display; + } + } + + return NULL; +} + +void GDS_ClearExt(struct GDS_Device* Device, bool full, ...) { + bool commit = true; + + if (full) { + GDS_Clear( Device, GDS_COLOR_BLACK ); + } else { + va_list args; + va_start(args, full); + commit = va_arg(args, int); + int x1 = va_arg(args, int), y1 = va_arg(args, int), x2 = va_arg(args, int), y2 = va_arg(args, int); + if (x2 < 0) x2 = Device->Width - 1; + if (y2 < 0) y2 = Device->Height - 1; + GDS_ClearWindow( Device, x1, y1, x2, y2, GDS_COLOR_BLACK ); + va_end(args); + } + + Device->Dirty = true; + if (commit) GDS_Update(Device); +} + +void GDS_Clear( struct GDS_Device* Device, int Color ) { + memset( Device->Framebuffer, Color, Device->FramebufferSize ); +} + +void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ) { + // cheap optimization on boundaries + if (x1 == 0 && x2 == Device->Width - 1 && y1 % 8 == 0 && (y2 + 1) % 8 == 0) { + memset( Device->Framebuffer + (y1 / 8) * Device->Width, 0, (y2 - y1 + 1) / 8 * Device->Width ); + } else { + for (int y = y1; y <= y2; y++) { + for (int x = x1; x <= x2; x++) { + Device->DrawPixelFast( Device, x, y, Color); + } + } + } +} + +void GDS_Update( struct GDS_Device* Device ) { + if (Device->Dirty) Device->Update( Device ); + Device->Dirty = false; +} + +bool GDS_Reset( struct GDS_Device* Device ) { + if ( Device->RSTPin >= 0 ) { + gpio_set_level( Device->RSTPin, 0 ); + vTaskDelay( pdMS_TO_TICKS( 100 ) ); + gpio_set_level( Device->RSTPin, 1 ); + } + 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 ); } +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 ); } \ No newline at end of file diff --git a/components/display/core/gds.h b/components/display/core/gds.h new file mode 100644 index 00000000..fed8455f --- /dev/null +++ b/components/display/core/gds.h @@ -0,0 +1,30 @@ +#ifndef _GDS_H_ +#define _GDS_H_ + +#include +#include + +#define GDS_COLOR_BLACK 0 +#define GDS_COLOR_WHITE 1 +#define GDS_COLOR_XOR 2 + +struct GDS_Device; +struct GDS_FontDef; + +typedef struct GDS_Device* (*GDS_DetectFunc)(char *Driver, struct GDS_Device *Device); + +struct GDS_Device* GDS_AutoDetect( char *Driver, GDS_DetectFunc[] ); + +void GDS_SetContrast( struct GDS_Device* Device, uint8_t Contrast ); +void GDS_DisplayOn( struct GDS_Device* Device ); +void GDS_DisplayOff( struct GDS_Device* Device ); +void GDS_Update( struct GDS_Device* Device ); +void GDS_SetHFlip( struct GDS_Device* Device, bool On ); +void GDS_SetVFlip( struct GDS_Device* Device, bool On ); +int GDS_GetWidth( struct GDS_Device* Device ); +int GDS_GetHeight( struct GDS_Device* Device ); +void GDS_ClearExt( struct GDS_Device* Device, bool full, ...); +void GDS_Clear( struct GDS_Device* Device, int Color ); +void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color ); + +#endif diff --git a/components/display/core/gds_default_if.h b/components/display/core/gds_default_if.h new file mode 100644 index 00000000..698cb5e1 --- /dev/null +++ b/components/display/core/gds_default_if.h @@ -0,0 +1,20 @@ +#ifndef _GDS_DEFAULT_IF_H_ +#define _GDS_DEFAULT_IF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct GDS_Device; + +bool GDS_I2CInit( int PortNumber, int SDA, int SCL ); +bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin ); + +bool GDS_SPIInit( int SPI, int DC ); +bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/display/core/gds_draw.c b/components/display/core/gds_draw.c new file mode 100644 index 00000000..ac9a5959 --- /dev/null +++ b/components/display/core/gds_draw.c @@ -0,0 +1,321 @@ +/** + * Copyright (c) 2017-2018 Tara Keeling + * 2020 Philippe G. + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "gds.h" +#include "gds_private.h" +#include "gds_draw.h" + +static const unsigned char BitReverseTable256[] = +{ + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +__attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct GDS_Device* Device, int x, int y ) { + bool Result = ( + ( x >= 0 ) && + ( x < Device->Width ) && + ( y >= 0 ) && + ( y < Device->Height ) + ) ? true : false; + +#if CONFIG_GDS_CLIPDEBUG > 0 + if ( Result == false ) { + ClipDebug( x, y ); + } +#endif + + return Result; +} + +__attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b ) { + int Temp = *b; + + *b = *a; + *a = Temp; +} + +inline void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) { + uint32_t YBit = ( Y & 0x07 ); + uint8_t* FBOffset = NULL; + + /* + * We only need to modify the Y coordinate since the pitch + * of the screen is the same as the width. + * Dividing Y by 8 gives us which row the pixel is in but not + * the bit position. + */ + Y>>= 3; + + FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X ); + + if ( Color == GDS_COLOR_XOR ) { + *FBOffset ^= BIT( YBit ); + } else { + *FBOffset = ( Color == GDS_COLOR_WHITE ) ? *FBOffset | BIT( YBit ) : *FBOffset & ~BIT( YBit ); + } +} + +void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int x, int y, int Color ) { + if ( IsPixelVisible( Device, x, y ) == true ) { + Device->DrawPixelFast( Device, x, y, Color ); + } +} + +inline void IRAM_ATTR GDS_DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ) { + uint32_t YBit = ( Y & 0x07 ); + uint8_t* FBOffset = NULL; + + /* + * We only need to modify the Y coordinate since the pitch + * of the screen is the same as the width. + * Dividing Y by 8 gives us which row the pixel is in but not + * the bit position. + */ + Y>>= 3; + + FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X ); + + if ( Color == GDS_COLOR_XOR ) { + *FBOffset ^= BIT( YBit ); + } else { + *FBOffset = ( Color == GDS_COLOR_WHITE ) ? *FBOffset | BIT( YBit ) : *FBOffset & ~BIT( YBit ); + } +} + +void IRAM_ATTR GDS_DrawPixel4( struct GDS_Device* Device, int x, int y, int Color ) { + if ( IsPixelVisible( Device, x, y ) == true ) { + Device->DrawPixelFast( Device, x, y, Color ); + } +} + +void IRAM_ATTR GDS_DrawHLine( struct GDS_Device* Device, int x, int y, int Width, int Color ) { + int XEnd = x + Width; + + Device->Dirty = true; + + if (x < 0) x = 0; + if (XEnd >= Device->Width) XEnd = Device->Width - 1; + + if (y < 0) y = 0; + else if (y >= Device->Height) x = Device->Height - 1; + + for ( ; x < XEnd; x++ ) { + // if ( IsPixelVisible( Device, x, y ) == true ) { + Device->DrawPixelFast( Device, x, y, Color ); + // } else { + // break; + // } + } +} + +void IRAM_ATTR GDS_DrawVLine( struct GDS_Device* Device, int x, int y, int Height, int Color ) { + int YEnd = y + Height; + + Device->Dirty = true; + + for ( ; y < YEnd; y++ ) { + if ( IsPixelVisible( Device, x, y ) == true ) { + Device->DrawPixel( Device, x, y, Color ); + } else { + break; + } + } +} + +static inline void IRAM_ATTR DrawWideLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ) { + int dx = ( x1 - x0 ); + int dy = ( y1 - y0 ); + int Error = 0; + int Incr = 1; + int x = x0; + int y = y0; + + if ( dy < 0 ) { + Incr = -1; + dy = -dy; + } + + Error = ( dy * 2 ) - dx; + + for ( ; x < x1; x++ ) { + if ( IsPixelVisible( Device, x, y ) == true ) { + Device->DrawPixelFast( Device, x, y, Color ); + } + + if ( Error > 0 ) { + Error-= ( dx * 2 ); + y+= Incr; + } + + Error+= ( dy * 2 ); + } +} + +static inline void IRAM_ATTR DrawTallLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ) { + int dx = ( x1 - x0 ); + int dy = ( y1 - y0 ); + int Error = 0; + int Incr = 1; + int x = x0; + int y = y0; + + if ( dx < 0 ) { + Incr = -1; + dx = -dx; + } + + Error = ( dx * 2 ) - dy; + + for ( ; y < y1; y++ ) { + if ( IsPixelVisible( Device, x, y ) == true ) { + Device->DrawPixelFast( Device, x, y, Color ); + } + + if ( Error > 0 ) { + Error-= ( dy * 2 ); + x+= Incr; + } + + Error+= ( dx * 2 ); + } +} + +void IRAM_ATTR GDS_DrawLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ) { + if ( x0 == x1 ) { + GDS_DrawVLine( Device, x0, y0, ( y1 - y0 ), Color ); + } else if ( y0 == y1 ) { + GDS_DrawHLine( Device, x0, y0, ( x1 - x0 ), Color ); + } else { + Device->Dirty = true; + if ( abs( x1 - x0 ) > abs( y1 - y0 ) ) { + /* Wide ( run > rise ) */ + if ( x0 > x1 ) { + SwapInt( &x0, &x1 ); + SwapInt( &y0, &y1 ); + } + + DrawWideLine( Device, x0, y0, x1, y1, Color ); + } else { + /* Tall ( rise > run ) */ + if ( y0 > y1 ) { + SwapInt( &y0, &y1 ); + SwapInt( &x0, &x1 ); + } + + DrawTallLine( Device, x0, y0, x1, y1, Color ); + } + } +} + +void IRAM_ATTR GDS_DrawBox( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color, bool Fill ) { + int Width = ( x2 - x1 ); + int Height = ( y2 - y1 ); + + Device->Dirty = true; + + if ( Fill == false ) { + /* Top side */ + GDS_DrawHLine( Device, x1, y1, Width, Color ); + + /* Bottom side */ + GDS_DrawHLine( Device, x1, y1 + Height, Width, Color ); + + /* Left side */ + GDS_DrawVLine( Device, x1, y1, Height, Color ); + + /* Right side */ + GDS_DrawVLine( Device, x1 + Width, y1, Height, Color ); + } else { + /* Fill the box by drawing horizontal lines */ + for ( ; y1 <= y2; y1++ ) { + GDS_DrawHLine( Device, x1, y1, Width, Color ); + } + } +} + + +/**************************************************************************************** + * Process graphic display data from column-oriented data (MSbit first) + */ +void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int Height) { + if (!Height) Height = Device->Height; + if (!Width) Width = Device->Width; + + // need to do row/col swap and bit-reverse + int Rows = Height / 8; + for (int r = 0; r < Rows; r++) { + uint8_t *optr = Device->Framebuffer + r*Device->Width, *iptr = Data + r; + for (int c = Width; --c >= 0;) { + *optr++ = BitReverseTable256[*iptr];; + iptr += Rows; + } + } + + Device->Dirty = true; +} + +/**************************************************************************************** + * Process graphic display data MSBit first + * WARNING: this has not been tested yet + */ + /* +static void draw_raw(int x1, int y1, int x2, int y2, bool by_column, bool MSb, u8_t *data) { + // default end point to display size + if (x2 == -1) x2 = Display.Width - 1; + if (y2 == -1) y2 = Display.Height - 1; + + display->dirty = true; + + // not a boundary draw + // same comment about bit depth + if (y1 % 8 || y2 % 8 || x1 % 8 | x2 % 8) { + ESP_LOGW(TAG, "can't write on non cols/rows boundaries for now"); + } else { + // set addressing mode to match data + if (by_column) { + // copy the window and do row/col exchange + for (int r = y1/8; r <= y2/8; r++) { + uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r; + for (int c = x1; c <= x2; c++) { + *optr++ = MSb ? BitReverseTable256[*iptr] : *iptr; + iptr += (y2-y1)/8 + 1; + } + } + } else { + // just copy the window inside the frame buffer + for (int r = y1/8; r <= y2/8; r++) { + uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r*(x2-x1+1); + for (int c = x1; c <= x2; c++) *optr++ = *iptr++; + } + } + } +} +*/ diff --git a/components/display/core/gds_draw.h b/components/display/core/gds_draw.h new file mode 100644 index 00000000..10bce8b8 --- /dev/null +++ b/components/display/core/gds_draw.h @@ -0,0 +1,26 @@ +#ifndef _GDS_DRAW_H_ +#define _GDS_DRAW_H_ + +#include +#include +#include "esp_attr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct GDS_Device; + +void IRAM_ATTR GDS_DrawHLine( struct GDS_Device* Device, int x, int y, int Width, int Color ); +void IRAM_ATTR GDS_DrawVLine( struct GDS_Device* Device, int x, int y, int Height, int Color ); +void IRAM_ATTR GDS_DrawLine( struct GDS_Device* Device, int x0, int y0, int x1, int y1, int Color ); +void IRAM_ATTR GDS_DrawBox( struct GDS_Device* Device, int x1, int y1, int x2, int y2, int Color, bool Fill ); + +// draw a bitmap with source 1-bit depth organized in column and col0 = bit7 of byte 0 +void IRAM_ATTR GDS_DrawBitmapCBR( struct GDS_Device* Device, uint8_t *Data, int Width, int Height); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/display/tarablessd13x6/ssd13x6_err.h b/components/display/core/gds_err.h similarity index 81% rename from components/display/tarablessd13x6/ssd13x6_err.h rename to components/display/core/gds_err.h index ee65a22d..827a24c6 100644 --- a/components/display/tarablessd13x6/ssd13x6_err.h +++ b/components/display/core/gds_err.h @@ -1,15 +1,15 @@ -#ifndef _SSD13x6_ERR_H_ -#define _SSD13x6_ERR_H_ +#ifndef _GDS_ERR_H_ +#define _GDS_ERR_H_ #include -#define SSD13x6_DoAbort( ) +#define GDS_DoAbort( ) #if ! defined NullCheck #define NullCheck( ptr, retexpr ) { \ if ( ptr == NULL ) { \ ESP_LOGE( __FUNCTION__, "%s == NULL", #ptr ); \ - SSD13x6_DoAbort( ); \ + GDS_DoAbort( ); \ retexpr; \ } \ } @@ -20,7 +20,7 @@ esp_err_t __err_rc = ( expr ); \ if ( __err_rc != ESP_OK ) { \ ESP_LOGE( __FUNCTION__, "%s != ESP_OK, result: %d", #expr, __err_rc ); \ - SSD13x6_DoAbort( ); \ + GDS_DoAbort( ); \ retexpr; \ } \ } @@ -30,7 +30,7 @@ #define CheckBounds( expr, retexpr ) { \ if ( expr ) { \ ESP_LOGE( __FUNCTION__, "Line %d: %s", __LINE__, #expr ); \ - SSD13x6_DoAbort( ); \ + GDS_DoAbort( ); \ retexpr; \ } \ } diff --git a/components/display/tarablessd13x6/ssd13x6_font.c b/components/display/core/gds_font.c similarity index 58% rename from components/display/tarablessd13x6/ssd13x6_font.c rename to components/display/core/gds_font.c index 37e9dbcb..b8dda265 100644 --- a/components/display/tarablessd13x6/ssd13x6_font.c +++ b/components/display/core/gds_font.c @@ -9,11 +9,13 @@ #include #include #include -#include "ssd13x6.h" -#include "ssd13x6_draw.h" -#include "ssd13x6_font.h" +#include "gds.h" +#include "gds_draw.h" +#include "gds_font.h" +#include "gds_private.h" +#include "gds_err.h" -static int RoundUpFontHeight( const struct SSD13x6_FontDef* Font ) { +static int RoundUpFontHeight( const struct GDS_FontDef* Font ) { int Height = Font->Height; if ( ( Height % 8 ) != 0 ) { @@ -23,11 +25,11 @@ static int RoundUpFontHeight( const struct SSD13x6_FontDef* Font ) { return Height; } -static const uint8_t* GetCharPtr( const struct SSD13x6_FontDef* Font, char Character ) { +static const uint8_t* GetCharPtr( const struct GDS_FontDef* Font, char Character ) { return &Font->FontData[ ( Character - Font->StartChar ) * ( ( Font->Width * ( RoundUpFontHeight( Font ) / 8 ) ) + 1 ) ]; } -void SSD13x6_FontDrawChar( struct SSD13x6_Device* DisplayHandle, char Character, int x, int y, int Color ) { +void GDS_FontDrawChar( struct GDS_Device* Device, char Character, int x, int y, int Color ) { const uint8_t* GlyphData = NULL; int GlyphColumnLen = 0; int CharStartX = 0; @@ -42,18 +44,15 @@ void SSD13x6_FontDrawChar( struct SSD13x6_Device* DisplayHandle, char Character, int YBit = 0; int i = 0; - NullCheck( DisplayHandle, return ); - NullCheck( DisplayHandle->Font, return ); - - NullCheck( ( GlyphData = GetCharPtr( DisplayHandle->Font, Character ) ), return ); + NullCheck( ( GlyphData = GetCharPtr( Device->Font, Character ) ), return ); - if ( Character >= DisplayHandle->Font->StartChar && Character <= DisplayHandle->Font->EndChar ) { + if ( Character >= Device->Font->StartChar && Character <= Device->Font->EndChar ) { /* The first byte in the glyph data is the width of the character in pixels, skip over */ GlyphData++; - GlyphColumnLen = RoundUpFontHeight( DisplayHandle->Font ) / 8; + GlyphColumnLen = RoundUpFontHeight( Device->Font ) / 8; - CharWidth = SSD13x6_FontGetCharWidth( DisplayHandle, Character ); - CharHeight = SSD13x6_FontGetHeight( DisplayHandle ); + CharWidth = GDS_FontGetCharWidth( Device, Character ); + CharHeight = GDS_FontGetHeight( Device ); CharStartX = x; CharStartY = y; @@ -74,14 +73,15 @@ void SSD13x6_FontDrawChar( struct SSD13x6_Device* DisplayHandle, char Character, CharStartY+= OffsetY; /* Do not attempt to draw if this character is entirely offscreen */ - if ( CharEndX < 0 || CharStartX >= DisplayHandle->Width || CharEndY < 0 || CharStartY >= DisplayHandle->Height ) { + if ( CharEndX < 0 || CharStartX >= Device->Width || CharEndY < 0 || CharStartY >= Device->Height ) { ClipDebug( x, y ); return; } /* Do not attempt to draw past the end of the screen */ - CharEndX = ( CharEndX >= DisplayHandle->Width ) ? DisplayHandle->Width - 1 : CharEndX; - CharEndY = ( CharEndY >= DisplayHandle->Height ) ? DisplayHandle->Height - 1 : CharEndY; + CharEndX = ( CharEndX >= Device->Width ) ? Device->Width - 1 : CharEndX; + CharEndY = ( CharEndY >= Device->Height ) ? Device->Height - 1 : CharEndY; + Device->Dirty = true; for ( x = CharStartX; x < CharEndX; x++ ) { for ( y = CharStartY, i = 0; y < CharEndY && i < CharHeight; y++, i++ ) { @@ -89,7 +89,7 @@ void SSD13x6_FontDrawChar( struct SSD13x6_Device* DisplayHandle, char Character, YBit = ( i + OffsetY ) & 0x07; if ( GlyphData[ YByte ] & BIT( YBit ) ) { - SSD13x6_DrawPixel( DisplayHandle, x, y, Color ); + Device->DrawPixel( Device, x, y, Color ); } } @@ -98,10 +98,7 @@ void SSD13x6_FontDrawChar( struct SSD13x6_Device* DisplayHandle, char Character, } } -bool SSD13x6_SetFont( struct SSD13x6_Device* Display, const struct SSD13x6_FontDef* Font ) { - NullCheck( Display, return false ); - NullCheck( Font, return false ); - +bool GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ) { Display->FontForceProportional = false; Display->FontForceMonospace = false; Display->Font = Font; @@ -109,41 +106,26 @@ bool SSD13x6_SetFont( struct SSD13x6_Device* Display, const struct SSD13x6_FontD return true; } -void SSD13x6_FontForceProportional( struct SSD13x6_Device* Display, bool Force ) { - NullCheck( Display, return ); - NullCheck( Display->Font, return ); - +void GDS_FontForceProportional( struct GDS_Device* Display, bool Force ) { Display->FontForceProportional = Force; } -void SSD13x6_FontForceMonospace( struct SSD13x6_Device* Display, bool Force ) { - NullCheck( Display, return ); - NullCheck( Display->Font, return ); - +void GDS_FontForceMonospace( struct GDS_Device* Display, bool Force ) { Display->FontForceMonospace = Force; } -int SSD13x6_FontGetWidth( struct SSD13x6_Device* Display ) { - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); - +int GDS_FontGetWidth( struct GDS_Device* Display ) { return Display->Font->Width; } -int SSD13x6_FontGetHeight( struct SSD13x6_Device* Display ) { - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); - +int GDS_FontGetHeight( struct GDS_Device* Display ) { return Display->Font->Height; } -int SSD13x6_FontGetCharWidth( struct SSD13x6_Device* Display, char Character ) { +int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ) { const uint8_t* CharPtr = NULL; int Width = 0; - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); - if ( Character >= Display->Font->StartChar && Character <= Display->Font->EndChar ) { CharPtr = GetCharPtr( Display->Font, Character ); @@ -161,82 +143,67 @@ int SSD13x6_FontGetCharWidth( struct SSD13x6_Device* Display, char Character ) { return Width; } -int SSD13x6_FontGetMaxCharsPerRow( struct SSD13x6_Device* Display ) { - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); - +int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ) { return Display->Width / Display->Font->Width; } -int SSD13x6_FontGetMaxCharsPerColumn( struct SSD13x6_Device* Display ) { - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); - +int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ) { return Display->Height / Display->Font->Height; } -int SSD13x6_FontGetCharHeight( struct SSD13x6_Device* Display ) { - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); - +int GDS_FontGetCharHeight( struct GDS_Device* Display ) { return Display->Font->Height; } -int SSD13x6_FontMeasureString( struct SSD13x6_Device* Display, const char* Text ) { +int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text ) { int Width = 0; int Len = 0; - NullCheck( Display, return 0 ); - NullCheck( Display->Font, return 0 ); NullCheck( Text, return 0 ); for ( Len = strlen( Text ); Len >= 0; Len--, Text++ ) { if ( *Text >= Display->Font->StartChar && *Text <= Display->Font->EndChar ) { - Width+= SSD13x6_FontGetCharWidth( Display, *Text ); + Width+= GDS_FontGetCharWidth( Display, *Text ); } } return Width; } -void SSD13x6_FontDrawString( struct SSD13x6_Device* Display, int x, int y, const char* Text, int Color ) { +void GDS_FontDrawString( struct GDS_Device* Display, int x, int y, const char* Text, int Color ) { int Len = 0; int i = 0; - NullCheck( Display, return ); - NullCheck( Display->Font, return ); NullCheck( Text, return ); for ( Len = strlen( Text ), i = 0; i < Len; i++ ) { - SSD13x6_FontDrawChar( Display, *Text, x, y, Color ); + GDS_FontDrawChar( Display, *Text, x, y, Color ); - x+= SSD13x6_FontGetCharWidth( Display, *Text ); + x+= GDS_FontGetCharWidth( Display, *Text ); Text++; } } -void SSD13x6_FontDrawAnchoredString( struct SSD13x6_Device* Display, TextAnchor Anchor, const char* Text, int Color ) { +void GDS_FontDrawAnchoredString( struct GDS_Device* Display, TextAnchor Anchor, const char* Text, int Color ) { int x = 0; int y = 0; - NullCheck( Display, return ); NullCheck( Text, return ); - SSD13x6_FontGetAnchoredStringCoords( Display, &x, &y, Anchor, Text ); - SSD13x6_FontDrawString( Display, x, y, Text, Color ); + GDS_FontGetAnchoredStringCoords( Display, &x, &y, Anchor, Text ); + GDS_FontDrawString( Display, x, y, Text, Color ); } -void SSD13x6_FontGetAnchoredStringCoords( struct SSD13x6_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ) { +void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ) { int StringWidth = 0; int StringHeight = 0; - NullCheck( Display, return ); NullCheck( OutX, return ); NullCheck( OutY, return ); NullCheck( Text, return ); - StringWidth = SSD13x6_FontMeasureString( Display, Text ); - StringHeight = SSD13x6_FontGetCharHeight( Display ); + StringWidth = GDS_FontMeasureString( Display, Text ); + StringHeight = GDS_FontGetCharHeight( Display ); switch ( Anchor ) { case TextAnchor_East: { diff --git a/components/display/core/gds_font.h b/components/display/core/gds_font.h new file mode 100644 index 00000000..f80c9825 --- /dev/null +++ b/components/display/core/gds_font.h @@ -0,0 +1,91 @@ +#ifndef _GDS_FONT_H_ +#define _GDS_FONT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct GDS_Device; + +/* + * X-GLCD Font format: + * + * First byte of glyph is it's width in pixels. + * Each data byte represents 8 pixels going down from top to bottom. + * + * Example glyph layout for a 16x16 font + * 'a': [Glyph width][Pixel column 0][Pixel column 1] where the number of pixel columns is the font height divided by 8 + * 'b': [Glyph width][Pixel column 0][Pixel column 1]... + * 'c': And so on... + */ + +struct GDS_FontDef { + const uint8_t* FontData; + + int Width; + int Height; + + int StartChar; + int EndChar; + + bool Monospace; +}; + +typedef enum { + TextAnchor_East = 0, + TextAnchor_West, + TextAnchor_North, + TextAnchor_South, + TextAnchor_NorthEast, + TextAnchor_NorthWest, + TextAnchor_SouthEast, + TextAnchor_SouthWest, + TextAnchor_Center +} TextAnchor; + +bool GDS_SetFont( struct GDS_Device* Display, const struct GDS_FontDef* Font ); + +void GDS_FontForceProportional( struct GDS_Device* Display, bool Force ); +void GDS_FontForceMonospace( struct GDS_Device* Display, bool Force ); + +int GDS_FontGetWidth( struct GDS_Device* Display ); +int GDS_FontGetHeight( struct GDS_Device* Display ); + +int GDS_FontGetMaxCharsPerRow( struct GDS_Device* Display ); +int GDS_FontGetMaxCharsPerColumn( struct GDS_Device* Display ); + +int GDS_FontGetCharWidth( struct GDS_Device* Display, char Character ); +int GDS_FontGetCharHeight( struct GDS_Device* Display ); +int GDS_FontMeasureString( struct GDS_Device* Display, const char* Text );\ + +void GDS_FontDrawChar( struct GDS_Device* Display, char Character, int x, int y, int Color ); +void GDS_FontDrawString( struct GDS_Device* Display, int x, int y, const char* Text, int Color ); +void GDS_FontDrawAnchoredString( struct GDS_Device* Display, TextAnchor Anchor, const char* Text, int Color ); +void GDS_FontGetAnchoredStringCoords( struct GDS_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ); + +extern const struct GDS_FontDef Font_droid_sans_fallback_11x13; +extern const struct GDS_FontDef Font_droid_sans_fallback_15x17; +extern const struct GDS_FontDef Font_droid_sans_fallback_24x28; + +extern const struct GDS_FontDef Font_droid_sans_mono_7x13; +extern const struct GDS_FontDef Font_droid_sans_mono_13x24; +extern const struct GDS_FontDef Font_droid_sans_mono_16x31; + +extern const struct GDS_FontDef Font_liberation_mono_9x15; +extern const struct GDS_FontDef Font_liberation_mono_13x21; +extern const struct GDS_FontDef Font_liberation_mono_17x30; + +extern const struct GDS_FontDef Font_Tarable7Seg_16x32; +extern const struct GDS_FontDef Font_Tarable7Seg_32x64; + +extern const struct GDS_FontDef Font_line_1; +extern const struct GDS_FontDef Font_line_2; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/display/core/gds_private.h b/components/display/core/gds_private.h new file mode 100644 index 00000000..52ce2766 --- /dev/null +++ b/components/display/core/gds_private.h @@ -0,0 +1,130 @@ +#pragma once + +#include +#include +#include "esp_attr.h" +#include "gds.h" +#include "gds_err.h" + +#define GDS_CLIPDEBUG_NONE 0 +#define GDS_CLIPDEBUG_WARNING 1 +#define GDS_CLIPDEBUG_ERROR 2 + +#define SHADOW_BUFFER + +#if CONFIG_GDS_CLIPDEBUG == GDS_CLIPDEBUG_NONE + /* + * Clip silently with no console output. + */ + #define ClipDebug( x, y ) +#elif CONFIG_GDS_CLIPDEBUG == GDS_CLIPDEBUG_WARNING + /* + * Log clipping to the console as a warning. + */ + #define ClipDebug( x, y ) { \ + ESP_LOGW( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED", __LINE__, x, y ); \ + } +#elif CONFIG_GDS_CLIPDEBUG == GDS_CLIPDEBUG_ERROR + /* + * Log clipping as an error to the console. + * Also invokes an abort with stack trace. + */ + #define ClipDebug( x, y ) { \ + ESP_LOGE( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED, ABORT", __LINE__, x, y ); \ + abort( ); \ + } +#endif + + +#define GDS_ALWAYS_INLINE __attribute__( ( always_inline ) ) + +#define MAX_LINES 8 + +#if ! defined BIT +#define BIT( n ) ( 1 << n ) +#endif + +typedef enum { + AddressMode_Horizontal = 0, + AddressMode_Vertical, + AddressMode_Page, + AddressMode_Invalid +} GDS_AddressMode; + +struct GDS_Device; +struct GDS_FontDef; + +/* + * These can optionally return a succeed/fail but are as of yet unused in the driver. + */ +typedef bool ( *WriteCommandProc ) ( struct GDS_Device* Device, uint8_t Command ); +typedef bool ( *WriteDataProc ) ( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); + +struct spi_device_t; +typedef struct spi_device_t* spi_device_handle_t; + +#define IF_SPI 0 +#define IF_I2C 1 + +struct GDS_Device { + uint8_t IF; + union { + // I2C Specific + struct { + uint8_t Address; + }; + // SPI specific + struct { + spi_device_handle_t SPIHandle; + int8_t RSTPin; + int8_t CSPin; + }; + }; + + // cooked text mode + struct { + int16_t Y, Space; + const struct GDS_FontDef* Font; + } Lines[MAX_LINES]; + + uint16_t Width; + uint16_t Height; + uint8_t Depth; + + uint8_t* Framebuffer, *Shadowbuffer; + uint16_t FramebufferSize; + bool Dirty; + + // default fonts when using direct draw + const struct GDS_FontDef* Font; + bool FontForceProportional; + bool FontForceMonospace; + + // various driver-specific method + bool (*Init)( struct GDS_Device* Device); + void (*SetContrast)( struct GDS_Device* Device, uint8_t Contrast ); + void (*DisplayOn)( struct GDS_Device* Device ); + void (*DisplayOff)( struct GDS_Device* Device ); + void (*Update)( struct GDS_Device* Device ); + void (*DrawPixel)( struct GDS_Device* Device, int X, int Y, int Color ); + void (*DrawPixelFast)( struct GDS_Device* Device, int X, int Y, int Color ); + void (*SetHFlip)( struct GDS_Device* Device, bool On ); + void (*SetVFlip)( struct GDS_Device* Device, bool On ); + + // interface-specific methods + WriteCommandProc WriteCommand; + WriteDataProc WriteData; +}; + +bool GDS_Reset( struct GDS_Device* Device ); + +/* +inline void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ); +void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int x, int y, int Color ); +inline void IRAM_ATTR GDS_DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ); +void IRAM_ATTR GDS_DrawPixel4( struct GDS_Device* Device, int x, int y, int Color ); +*/ +void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ); +void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int x, int y, int Color ); +void IRAM_ATTR GDS_DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ); +void IRAM_ATTR GDS_DrawPixel4( struct GDS_Device* Device, int x, int y, int Color ); diff --git a/components/display/core/gds_text.c b/components/display/core/gds_text.c new file mode 100644 index 00000000..a72613e5 --- /dev/null +++ b/components/display/core/gds_text.c @@ -0,0 +1,195 @@ +/* + * (c) 2004,2006 Richard Titmuss for SlimProtoLib + * (c) Philippe G. 2019, philippe_44@outlook.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include +#include +#include "esp_log.h" +#include "gds.h" +#include "gds_draw.h" +#include "gds_text.h" +#include "gds_private.h" + +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +static char TAG[] = "gds"; + +/**************************************************************************************** + * Set fonts for each line in text mode + */ +static const struct GDS_FontDef *GuessFont( struct GDS_Device *Device, int FontType) { + switch(FontType) { + case GDS_FONT_LINE_1: + return &Font_line_1; + case GDS_FONT_LINE_2: + return &Font_line_2; + case GDS_FONT_SMALL: + return &Font_droid_sans_fallback_11x13; + case GDS_FONT_MEDIUM: + default: + return &Font_droid_sans_fallback_15x17; + case GDS_FONT_LARGE: + return &Font_droid_sans_fallback_24x28; + break; + case GDS_FONT_SEGMENT: + if (Device->Height == 32) return &Font_Tarable7Seg_16x32; + else return &Font_Tarable7Seg_32x64; + } +} + + +/**************************************************************************************** + * Set fonts for each line in text mode + */ +bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space) { + const struct GDS_FontDef *Font = GuessFont( Device, FontType ); + return GDS_TextSetFont( Device, N, Font, Space ); +} + +/**************************************************************************************** + * Set fonts for each line in text mode + */ +bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space) { + if (--N >= MAX_LINES) return false; + + Device->Lines[N].Font = Font; + + // re-calculate lines absolute position + Device->Lines[N].Space = Space; + Device->Lines[0].Y = Device->Lines[0].Space; + for (int i = 1; i <= N; i++) Device->Lines[i].Y = Device->Lines[i-1].Y + Device->Lines[i-1].Font->Height + Device->Lines[i].Space; + + ESP_LOGI(TAG, "Adding line %u at %d (height:%u)", N + 1, Device->Lines[N].Y, Device->Lines[N].Font->Height); + + if (Device->Lines[N].Y + Device->Lines[N].Font->Height > Device->Height) { + ESP_LOGW(TAG, "line does not fit display"); + return false; + } + + return true; +} + +/**************************************************************************************** + * + */ +bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text) { + int Width, X = Pos; + + // counting 1..n + N--; + + GDS_SetFont( Device, Device->Lines[N].Font ); + if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true ); + + Width = GDS_FontMeasureString( Device, Text ); + + // adjusting position, erase only EoL for rigth-justified + if (Pos == GDS_TEXT_RIGHT) X = Device->Width - Width - 1; + else if (Pos == GDS_TEXT_CENTER) X = (Device->Width - Width) / 2; + + // erase if requested + if (Attr & GDS_TEXT_CLEAR) { + int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height); + for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->Width; c++) + for (int y = Y_min; y < Y_max; y++) + Device->DrawPixelFast( Device, c, y, GDS_COLOR_BLACK ); + } + + GDS_FontDrawString( Device, X, Device->Lines[N].Y, Text, GDS_COLOR_WHITE ); + + ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", Text, N+1, X, Attr); + + // update whole display if requested + Device->Dirty = true; + if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device ); + + return Width + X < Device->Width; +} + +/**************************************************************************************** + * Try to align string for better scrolling visual. there is probably much better to do + */ +int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) { + char Space[] = " "; + int Len = strlen(String), Extra = 0, Boundary; + + N--; + + // we might already fit + GDS_SetFont( Device, Device->Lines[N].Font ); + if (GDS_FontMeasureString( Device, String ) <= Device->Width) return 0; + + // add some space for better visual + strncat(String, Space, Max-Len); + String[Max] = '\0'; + Len = strlen(String); + + // mark the end of the extended string + Boundary = GDS_FontMeasureString( Device, String ); + + // add a full display width + while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->Width) { + String[Len++] = String[Extra++]; + String[Len] = '\0'; + } + + return Boundary; +} + +/**************************************************************************************** + * + */ +void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...) { + va_list args; + + TextAnchor Anchor = TextAnchor_Center; + + if (Attr & GDS_TEXT_CLEAR) GDS_Clear( Device, GDS_COLOR_BLACK ); + + if (!Text) return; + + va_start(args, Text); + + switch(Where) { + case GDS_TEXT_TOP_LEFT: + default: + Anchor = TextAnchor_NorthWest; + break; + case GDS_TEXT_MIDDLE_LEFT: + Anchor = TextAnchor_West; + break; + case GDS_TEXT_BOTTOM_LEFT: + Anchor = TextAnchor_SouthWest; + break; + case GDS_TEXT_CENTERED: + Anchor = TextAnchor_Center; + break; + } + + ESP_LOGD(TAG, "Displaying %s at %u with attribute %u", Text, Anchor, Attr); + + GDS_SetFont( Device, GuessFont( Device, FontType ) ); + GDS_FontDrawAnchoredString( Device, Anchor, Text, GDS_COLOR_WHITE ); + + Device->Dirty = true; + if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device ); + + va_end(args); +} diff --git a/components/display/core/gds_text.h b/components/display/core/gds_text.h new file mode 100644 index 00000000..50652938 --- /dev/null +++ b/components/display/core/gds_text.h @@ -0,0 +1,45 @@ +/* + * (c) Philippe G. 2019, philippe_44@outlook.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "gds_font.h" + +#define GDS_TEXT_CLEAR 0x01 +#define GDS_TEXT_CLEAR_EOL 0x02 +#define GDS_TEXT_UPDATE 0x04 +#define GDS_TEXT_MONOSPACE 0x08 + +// these ones are for 'Pos' parameter of TextLine +#define GDS_TEXT_LEFT 0 +#define GDS_TEXT_RIGHT 0xff00 +#define GDS_TEXT_CENTER 0xff01 + +// these ones are for the 'Where' parameter of TextPos +enum { GDS_TEXT_TOP_LEFT, GDS_TEXT_MIDDLE_LEFT, GDS_TEXT_BOTTOM_LEFT, GDS_TEXT_CENTERED }; + +enum { GDS_FONT_DEFAULT, GDS_FONT_LINE_1, GDS_FONT_LINE_2, GDS_FONT_SEGMENT, + GDS_FONT_TINY, GDS_FONT_SMALL, GDS_FONT_MEDIUM, GDS_FONT_LARGE, GDS_FONT_FONT_HUGE }; + +struct GDS_Device; + +bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space); +bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space); +bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text); +int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max); +void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...); \ No newline at end of file diff --git a/components/display/tarablessd13x6/ifaces/default_if_i2c.c b/components/display/core/ifaces/default_if_i2c.c similarity index 58% rename from components/display/tarablessd13x6/ifaces/default_if_i2c.c rename to components/display/core/ifaces/default_if_i2c.c index d5e6010b..a2b80c8b 100644 --- a/components/display/tarablessd13x6/ifaces/default_if_i2c.c +++ b/components/display/core/ifaces/default_if_i2c.c @@ -11,18 +11,19 @@ #include #include #include -#include "ssd13x6.h" -#include "ssd13x6_default_if.h" +#include "gds.h" +#include "gds_err.h" +#include "gds_private.h" +#include "gds_default_if.h" static int I2CPortNumber; -static const int SSD13x6_I2C_COMMAND_MODE = 0x80; -static const int SSD13x6_I2C_DATA_MODE = 0x40; +static const int GDS_I2C_COMMAND_MODE = 0x80; +static const int GDS_I2C_DATA_MODE = 0x40; static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength ); -static bool I2CDefaultWriteCommand( struct SSD13x6_Device* Display, SSDCmd Command ); -static bool I2CDefaultWriteData( struct SSD13x6_Device* Display, const uint8_t* Data, size_t DataLength ); -static bool I2CDefaultReset( struct SSD13x6_Device* Display ); +static bool I2CDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ); +static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); /* * Initializes the i2c master with the parameters specified @@ -30,7 +31,7 @@ static bool I2CDefaultReset( struct SSD13x6_Device* Display ); * * Returns true on successful init of the i2c bus. */ -bool SSD13x6_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) { +bool GDS_I2CInit( int PortNumber, int SDA, int SCL ) { I2CPortNumber = PortNumber; if (SDA != -1 && SCL != -1) { @@ -54,7 +55,7 @@ bool SSD13x6_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) { * Attaches a display to the I2C bus using default communication functions. * * Params: - * DisplayHandle: Pointer to your SSD13x6_Device object + * Device: Pointer to your GDS_Device object * Width: Width of display * Height: Height of display * I2CAddress: Address of your display @@ -62,26 +63,24 @@ bool SSD13x6_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ) { * * Returns true on successful init of display. */ -bool SSD13x6_I2CMasterAttachDisplayDefault( struct SSD13x6_Device* DeviceHandle, int Model, int Width, int Height, int I2CAddress, int RSTPin ) { - NullCheck( DeviceHandle, return false ); +bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int I2CAddress, int RSTPin ) { + NullCheck( Device, return false ); - if ( RSTPin >= 0 ) { + Device->WriteCommand = I2CDefaultWriteCommand; + Device->WriteData = I2CDefaultWriteData; + Device->Address = I2CAddress; + Device->RSTPin = RSTPin; + Device->IF = IF_I2C; + Device->Width = Width; + Device->Height = Height; + + if ( RSTPin >= 0 ) { ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 1 ), return false ); + GDS_Reset( Device ); } - memset( DeviceHandle, 0, sizeof( struct SSD13x6_Device ) ); - DeviceHandle->Model = Model; - - return SSD13x6_Init_I2C( DeviceHandle, - Width, - Height, - I2CAddress, - RSTPin, - I2CDefaultWriteCommand, - I2CDefaultWriteData, - I2CDefaultReset - ); + return Device->Init( Device ); } static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Data, size_t DataLength ) { @@ -91,7 +90,7 @@ static bool I2CDefaultWriteBytes( int Address, bool IsCommand, const uint8_t* Da NullCheck( Data, return false ); if ( ( CommandHandle = i2c_cmd_link_create( ) ) != NULL ) { - ModeByte = ( IsCommand == true ) ? SSD13x6_I2C_COMMAND_MODE: SSD13x6_I2C_DATA_MODE; + ModeByte = ( IsCommand == true ) ? GDS_I2C_COMMAND_MODE: GDS_I2C_DATA_MODE; ESP_ERROR_CHECK_NONFATAL( i2c_master_start( CommandHandle ), goto error ); ESP_ERROR_CHECK_NONFATAL( i2c_master_write_byte( CommandHandle, ( Address << 1 ) | I2C_MASTER_WRITE, true ), goto error ); @@ -110,29 +109,16 @@ error: return false; } -static bool I2CDefaultWriteCommand( struct SSD13x6_Device* Display, SSDCmd Command ) { +static bool I2CDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ) { uint8_t CommandByte = ( uint8_t ) Command; - - NullCheck( Display, return false ); - return I2CDefaultWriteBytes( Display->Address, true, ( const uint8_t* ) &CommandByte, 1 ); + + NullCheck( Device, return false ); + return I2CDefaultWriteBytes( Device->Address, true, ( const uint8_t* ) &CommandByte, 1 ); } -static bool I2CDefaultWriteData( struct SSD13x6_Device* Display, const uint8_t* Data, size_t DataLength ) { - NullCheck( Display, return false ); +static bool I2CDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ) { + NullCheck( Device, return false ); NullCheck( Data, return false ); - return I2CDefaultWriteBytes( Display->Address, false, Data, DataLength ); + return I2CDefaultWriteBytes( Device->Address, false, Data, DataLength ); } - -static bool I2CDefaultReset( struct SSD13x6_Device* Display ) { - NullCheck( Display, return false ); - - if ( Display->RSTPin >= 0 ) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( Display->RSTPin, 0 ), return true ); - vTaskDelay( pdMS_TO_TICKS( 100 ) ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( Display->RSTPin, 1 ), return true ); - } - - return true; -} - diff --git a/components/display/core/ifaces/default_if_spi.c b/components/display/core/ifaces/default_if_spi.c new file mode 100644 index 00000000..0bfb7c4e --- /dev/null +++ b/components/display/core/ifaces/default_if_spi.c @@ -0,0 +1,109 @@ + +/** + * Copyright (c) 2017-2018 Tara Keeling + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include +#include +#include "gds.h" +#include "gds_err.h" +#include "gds_private.h" +#include "gds_default_if.h" + +static const int GDS_SPI_Command_Mode = 0; +static const int GDS_SPI_Data_Mode = 1; + +static spi_host_device_t SPIHost; +static int DCPin; + +static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ); +static bool SPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ); +static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ); + +bool GDS_SPIInit( int SPI, int DC ) { + SPIHost = SPI; + DCPin = DC; + return true; +} + +bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed ) { + spi_device_interface_config_t SPIDeviceConfig; + spi_device_handle_t SPIDevice; + + NullCheck( Device, return false ); + + if (CSPin >= 0) { + ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false ); + ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false ); + } + + memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) ); + + SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M; + SPIDeviceConfig.spics_io_num = CSPin; + SPIDeviceConfig.queue_size = 1; + + ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDevice ), return false ); + + Device->WriteCommand = SPIDefaultWriteCommand; + Device->WriteData = SPIDefaultWriteData; + Device->SPIHandle = SPIDevice; + Device->RSTPin = RSTPin; + Device->CSPin = CSPin; + Device->IF = IF_SPI; + Device->Width = Width; + Device->Height = Height; + + if ( RSTPin >= 0 ) { + ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); + ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 0 ), return false ); + GDS_Reset( Device ); + } + + return Device->Init( Device ); +} + +static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) { + spi_transaction_t SPITransaction = { 0 }; + + NullCheck( SPIHandle, return false ); + NullCheck( Data, return false ); + + if ( DataLength > 0 ) { + gpio_set_level( DCPin, WriteMode ); + + SPITransaction.length = DataLength * 8; + SPITransaction.tx_buffer = Data; + + // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) + ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false ); + } + + return true; +} + +static bool SPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ) { + static uint8_t CommandByte = 0; + + NullCheck( Device, return false ); + NullCheck( Device->SPIHandle, return false ); + + CommandByte = Command; + + return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Command_Mode, &CommandByte, 1 ); +} + +static bool SPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ) { + NullCheck( Device, return false ); + NullCheck( Device->SPIHandle, return false ); + + return SPIDefaultWriteBytes( Device->SPIHandle, GDS_SPI_Data_Mode, Data, DataLength ); +} \ No newline at end of file diff --git a/components/display/display.c b/components/display/display.c index 03713e5b..f8f00f38 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -22,14 +22,15 @@ #include #include #include "esp_log.h" +#include "globdefs.h" #include "config.h" #include "tools.h" #include "display.h" - -// here we should include all possible drivers -extern struct display_s SSD13x6_display; - -struct display_s *display = NULL; +#include "gds.h" +#include "gds_default_if.h" +#include "gds_draw.h" +#include "gds_text.h" +#include "gds_font.h" static const char *TAG = "display"; @@ -57,34 +58,74 @@ static EXT_RAM_ATTR struct { static void displayer_task(void *args); +struct GDS_Device *display; +struct GDS_Device* SSD1306_Detect(char *Driver, struct GDS_Device* Device); +struct GDS_Device* SH1106_Detect(char *Driver, struct GDS_Device* Device); +GDS_DetectFunc drivers[] = { SH1106_Detect, SSD1306_Detect, NULL }; + /**************************************************************************************** * */ void display_init(char *welcome) { bool init = false; - char *item = config_alloc_get(NVS_TYPE_STR, "display_config"); + char *config = config_alloc_get(NVS_TYPE_STR, "display_config"); - if (item && *item) { - char * drivername=strstr(item,"driver"); - if (!drivername || (drivername && (strcasestr(drivername,"SSD1306") || strcasestr(drivername,"SSD1326") || strcasestr(drivername,"SH1106")))) { - display = &SSD13x6_display; - if (display->init(item, welcome)) { - init = true; - ESP_LOGI(TAG, "Display initialization successful"); - } else { - display = NULL; - ESP_LOGW(TAG, "Display initialization failed"); - } + if (!config) { + ESP_LOGI(TAG, "no display"); + return false; + } + + int width = -1, height = -1; + char *p, *drivername = strstr(config, "driver"); + + // query drivers to see if we have a match + ESP_LOGI(TAG, "Trying to configure display with %s", config); + display = GDS_AutoDetect(drivername ? drivername : "SSD1306", drivers); + + if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1); + + // so far so good + if (display && width > 0 && height > 0) { + // Detect driver interface + if (strstr(config, "I2C") && i2c_system_port != -1) { + int address = 0x3C; + + if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1); + + init = true; + GDS_I2CInit( i2c_system_port, -1, -1 ) ; + GDS_I2CAttachDevice( display, width, height, address, -1 ); + + ESP_LOGI(TAG, "Display is I2C on port %u", address); + } else if (strstr(config, "SPI") && spi_system_host != -1) { + int CS_pin = -1, speed = 0; + + if ((p = strcasestr(config, "cs")) != NULL) CS_pin = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(config, "speed")) != NULL) speed = atoi(strchr(p, '=') + 1); + + init = true; + GDS_SPIInit( spi_system_host, spi_system_dc_gpio ); + GDS_SPIAttachDevice( display, width, height, CS_pin, -1, speed ); + + ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin); } else { - ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item); + display = NULL; + ESP_LOGI(TAG, "Unsupported display interface or serial link not configured"); } } else { - ESP_LOGI(TAG, "no display"); - } + display = NULL; + ESP_LOGW(TAG, "No display driver"); + } if (init) { static DRAM_ATTR StaticTask_t xTaskBuffer __attribute__ ((aligned (4))); static EXT_RAM_ATTR StackType_t xStack[DISPLAYER_STACK_SIZE] __attribute__ ((aligned (4))); + + GDS_SetHFlip(display, strcasestr(config, "HFlip") ? true : false); + GDS_SetVFlip(display, strcasestr(config, "VFlip") ? true : false); + GDS_SetFont(display, &Font_droid_sans_fallback_15x17 ); + GDS_TextPos(display, GDS_FONT_MEDIUM, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, welcome); // start the task that will handle scrolling & counting displayer.mutex = xSemaphoreCreateMutex(); @@ -94,13 +135,13 @@ void display_init(char *welcome) { displayer.task = xTaskCreateStatic( (TaskFunction_t) displayer_task, "displayer_thread", DISPLAYER_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, &xTaskBuffer); // set lines for "fixed" text mode - display->set_font(1, DISPLAY_FONT_LINE_1, -3); - display->set_font(2, DISPLAY_FONT_LINE_2, -3); + GDS_TextSetFontAuto(display, 1, GDS_FONT_LINE_1, -3); + GDS_TextSetFontAuto(display, 2, GDS_FONT_LINE_2, -3); displayer.metadata_config = config_alloc_get(NVS_TYPE_STR, "metadata_config"); } - if (item) free(item); + free(config); } /**************************************************************************************** @@ -114,14 +155,14 @@ static void displayer_task(void *args) { while (1) { // suspend ourselves if nothing to do if (displayer.state < DISPLAYER_ACTIVE) { - if (displayer.state == DISPLAYER_IDLE) display->line(2, 0, DISPLAY_CLEAR | DISPLAY_UPDATE, displayer.string); + if (displayer.state == DISPLAYER_IDLE) GDS_TextLine(display, 2, 0, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, displayer.string); vTaskSuspend(NULL); scroll_sleep = 0; - display->clear(true); - display->line(1, DISPLAY_LEFT, DISPLAY_UPDATE, displayer.header); + GDS_ClearExt(display, true); + GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_UPDATE, displayer.header); } else if (displayer.refresh) { // little trick when switching master while in IDLE and missing it - display->line(1, DISPLAY_LEFT, DISPLAY_CLEAR | DISPLAY_UPDATE, displayer.header); + GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, displayer.header); displayer.refresh = false; } @@ -140,7 +181,7 @@ static void displayer_task(void *args) { xSemaphoreGive(displayer.mutex); // now display using safe copies, can be lengthy - display->line(2, offset, DISPLAY_CLEAR | DISPLAY_UPDATE, string); + GDS_TextLine(display, 2, offset, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, string); free(string); } else { scroll_sleep = DEFAULT_SLEEP; @@ -160,7 +201,7 @@ static void displayer_task(void *args) { xSemaphoreGive(displayer.mutex); if (displayer.elapsed < 3600) sprintf(counter, "%5u:%02u", displayer.elapsed / 60, displayer.elapsed % 60); else sprintf(counter, "%2u:%02u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60); - display->line(1, DISPLAY_RIGHT, (DISPLAY_CLEAR | DISPLAY_ONLY_EOL) | DISPLAY_UPDATE, counter); + GDS_TextLine(display, 1, GDS_TEXT_RIGHT, (GDS_TEXT_CLEAR | GDS_TEXT_CLEAR_EOL) | GDS_TEXT_UPDATE, counter); timer_sleep = 1000; } else timer_sleep = max(1000 - elapsed, 0); } else timer_sleep = DEFAULT_SLEEP; @@ -240,7 +281,7 @@ void displayer_metadata(char *artist, char *album, char *title) { displayer.offset = 0; utf8_decode(displayer.string); ESP_LOGI(TAG, "playing %s", displayer.string); - displayer.boundary = display->stretch(2, displayer.string, SCROLLABLE_SIZE); + displayer.boundary = GDS_TextStretch(display, 2, displayer.string, SCROLLABLE_SIZE); xSemaphoreGive(displayer.mutex); } @@ -258,7 +299,7 @@ void displayer_scroll(char *string, int speed) { displayer.offset = 0; strncpy(displayer.string, string, SCROLLABLE_SIZE); displayer.string[SCROLLABLE_SIZE] = '\0'; - displayer.boundary = display->stretch(2, displayer.string, SCROLLABLE_SIZE); + displayer.boundary = GDS_TextStretch(display, 2, displayer.string, SCROLLABLE_SIZE); xSemaphoreGive(displayer.mutex); } diff --git a/components/display/display.h b/components/display/display.h index da2bb4f4..98b2dc92 100644 --- a/components/display/display.h +++ b/components/display/display.h @@ -18,6 +18,8 @@ #pragma once +#include "gds.h" + /* The displayer is not thread-safe and the caller must ensure use its own mutexes if it wants something better. Especially, text() line() and draw() @@ -32,44 +34,11 @@ when this one (the main) wants to take control over display, it can signal that to others */ +extern struct GDS_Device *display; -#define DISPLAY_CLEAR 0x01 -#define DISPLAY_ONLY_EOL 0x02 -#define DISPLAY_UPDATE 0x04 -#define DISPLAY_MONOSPACE 0x08 - -// these ones are for 'x' parameter of line() function -#define DISPLAY_LEFT 0 -#define DISPLAY_RIGHT 0xff00 -#define DISPLAY_CENTER 0xff01 - -enum display_pos_e { DISPLAY_TOP_LEFT, DISPLAY_MIDDLE_LEFT, DISPLAY_BOTTOM_LEFT, DISPLAY_CENTERED }; -enum display_font_e { DISPLAY_FONT_DEFAULT, - DISPLAY_FONT_LINE_1, DISPLAY_FONT_LINE_2, DISPLAY_FONT_SEGMENT, - DISPLAY_FONT_TINY, DISPLAY_FONT_SMALL, DISPLAY_FONT_MEDIUM, DISPLAY_FONT_LARGE, DISPLAY_FONT_HUGE }; - enum displayer_cmd_e { DISPLAYER_SHUTDOWN, DISPLAYER_ACTIVATE, DISPLAYER_SUSPEND, DISPLAYER_TIMER_PAUSE, DISPLAYER_TIMER_RUN }; enum displayer_time_e { DISPLAYER_ELAPSED, DISPLAYER_REMAINING }; -// don't change anything there w/o changing all drivers init code -extern struct display_s { - int width, height; - bool dirty; - bool (*init)(char *config, char *welcome); - void (*clear)(bool full, ...); - bool (*set_font)(int num, enum display_font_e font, int space); - void (*on)(bool state); - void (*brightness)(uint8_t level); - void (*text)(enum display_font_e font, enum display_pos_e pos, int attribute, char *msg, ...); - bool (*line)(int num, int x, int attribute, char *text); - int (*stretch)(int num, char *string, int max); - void (*update)(void); - void (*draw_raw)(int x1, int y1, int x2, int y2, bool by_column, bool MSb, uint8_t *data); - void (*draw_cbr)(uint8_t *data, int width, int height); // width and height is the # of rows/columns in data, as opposed to display height (0 = display width, 0 = display height) - void (*draw_line)(int x1, int y1, int x2, int y2); - void (*draw_box)( int x1, int y1, int x2, int y2, bool fill); -} *display; - enum display_bus_cmd_e { DISPLAY_BUS_TAKE, DISPLAY_BUS_GIVE }; bool (*display_bus)(void *from, enum display_bus_cmd_e cmd); diff --git a/components/display/driver_SSD13x6.c b/components/display/driver_SSD13x6.c deleted file mode 100644 index f2fd8cc5..00000000 --- a/components/display/driver_SSD13x6.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * (c) 2004,2006 Richard Titmuss for SlimProtoLib - * (c) Philippe G. 2019, philippe_44@outlook.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include -#include -#include -#include -#include "esp_log.h" -#include "display.h" -#include "globdefs.h" - -#include "ssd13x6.h" -#include "ssd13x6_draw.h" -#include "ssd13x6_font.h" -#include "ssd13x6_default_if.h" - -#define I2C_ADDRESS 0x3C - -static const char *TAG = "display"; - -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -// handlers -static bool init(char *config, char *welcome); -static void clear(bool full, ...); -static bool set_font(int num, enum display_font_e font, int space); -static void text(enum display_font_e font, enum display_pos_e pos, int attribute, char *text, ...); -static bool line(int num, int x, int attribute, char *text); -static int stretch(int num, char *string, int max); -static void draw_cbr(u8_t *data, int width, int height); -static void draw_raw(int x1, int y1, int x2, int y2, bool by_column, bool MSb, u8_t *data); -static void draw_line(int x1, int y1, int x2, int y2); -static void draw_box( int x1, int y1, int x2, int y2, bool fill); -static void brightness(u8_t level); -static void on(bool state); -static void update(void); - -// display structure for others to use -struct display_s SSD13x6_display = { 0, 0, true, - init, clear, set_font, on, brightness, - text, line, stretch, update, draw_raw, draw_cbr, draw_line, draw_box }; - -// SSD13x6 specific function -static struct SSD13x6_Device Display; - -static const unsigned char BitReverseTable256[] = -{ - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; - -#define MAX_LINES 8 - -static struct { - int y, space; - const struct SSD13x6_FontDef *font; -} lines[MAX_LINES]; - -/**************************************************************************************** - * - */ -static bool init(char *config, char *welcome) { - bool res = true; - int width = -1, height = -1, model = SSD1306; - char *p; - - ESP_LOGI(TAG, "Initializing display with config: %s",config); - - // no time for smart parsing - this is for tinkerers - if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1); - - if (strcasestr(config, "ssd1326")) model = SSD1326; - else if (strcasestr(config, "sh1106")) model = SH1106; - - if (width == -1 || height == -1) { - ESP_LOGW(TAG, "No display configured %s [%d x %d]", config, width, height); - return false; - } - - if (strstr(config, "I2C") && i2c_system_port != -1) { - int address = I2C_ADDRESS; - - if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1); - - SSD13x6_I2CMasterInitDefault( i2c_system_port, -1, -1 ) ; - SSD13x6_I2CMasterAttachDisplayDefault( &Display, model, width, height, address, -1 ); - SSD13x6_SetHFlip( &Display, strcasestr(config, "HFlip") ? true : false); - SSD13x6_SetVFlip( &Display, strcasestr(config, "VFlip") ? true : false); - SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_15x17 ); - SSD13x6_display.width = width; - SSD13x6_display.height = height; - - text(DISPLAY_FONT_MEDIUM, DISPLAY_CENTERED, DISPLAY_CLEAR | DISPLAY_UPDATE, welcome); - - ESP_LOGI(TAG, "Display is I2C on port %u", address); - } else if (strstr(config, "SPI") && spi_system_host != -1) { - int CS_pin = -1, speed = 0; - - if ((p = strcasestr(config, "cs")) != NULL) CS_pin = atoi(strchr(p, '=') + 1); - if ((p = strcasestr(config, "speed")) != NULL) speed = atoi(strchr(p, '=') + 1); - - SSD13x6_SPIMasterInitDefault( spi_system_host, spi_system_dc_gpio ); - SSD13x6_SPIMasterAttachDisplayDefault( &Display, model, width, height, CS_pin, -1, speed ); - SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_15x17 ); - SSD13x6_display.width = width; - SSD13x6_display.height = height; - - text(DISPLAY_FONT_MEDIUM, DISPLAY_CENTERED, DISPLAY_CLEAR | DISPLAY_UPDATE, welcome); - - ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin); - - } else { - res = false; - ESP_LOGW(TAG, "Unknown display type or no serial interface configured"); - } - - return res; -} - -/**************************************************************************************** - * - */ -static void clear(bool full, ...) { - bool commit = true; - - if (full) { - SSD13x6_Clear( &Display, SSD_COLOR_BLACK ); - } else { - va_list args; - va_start(args, full); - commit = va_arg(args, int); - int x1 = va_arg(args, int), y1 = va_arg(args, int), x2 = va_arg(args, int), y2 = va_arg(args, int); - if (x2 < 0) x2 = display->width - 1; - if (y2 < 0) y2 = display->height - 1; - SSD13x6_ClearWindow( &Display, x1, y1, x2, y2, SSD_COLOR_BLACK ); - va_end(args); - } - - SSD13x6_display.dirty = true; - if (commit) update(); -} - -/**************************************************************************************** - * Set fonts for each line in text mode - */ -static bool set_font(int num, enum display_font_e font, int space) { - if (--num >= MAX_LINES) return false; - - switch(font) { - case DISPLAY_FONT_LINE_1: - lines[num].font = &Font_line_1; - break; - case DISPLAY_FONT_LINE_2: - lines[num].font = &Font_line_2; - break; - case DISPLAY_FONT_SMALL: - lines[num].font = &Font_droid_sans_fallback_11x13; - break; - case DISPLAY_FONT_MEDIUM: - case DISPLAY_FONT_DEFAULT: - default: - lines[num].font = &Font_droid_sans_fallback_15x17; - break; - case DISPLAY_FONT_LARGE: - lines[num].font = &Font_droid_sans_fallback_24x28; - break; - case DISPLAY_FONT_SEGMENT: - if (Display.Height == 32) lines[num].font = &Font_Tarable7Seg_16x32; - else lines[num].font = &Font_Tarable7Seg_32x64; - break; - } - - // re-calculate lines absolute position - lines[num].space = space; - lines[0].y = lines[0].space; - for (int i = 1; i <= num; i++) lines[i].y = lines[i-1].y + lines[i-1].font->Height + lines[i].space; - - ESP_LOGI(TAG, "Adding line %u at %d (height:%u)", num + 1, lines[num].y, lines[num].font->Height); - - if (lines[num].y + lines[num].font->Height > Display.Height) { - ESP_LOGW(TAG, "line does not fit display"); - return false; - } - - return true; -} - -/**************************************************************************************** - * - */ -static bool line(int num, int x, int attribute, char *text) { - int width; - - // counting 1..n - num--; - - SSD13x6_SetFont( &Display, lines[num].font ); - if (attribute & DISPLAY_MONOSPACE) SSD13x6_FontForceMonospace( &Display, true ); - - width = SSD13x6_FontMeasureString( &Display, text ); - - // adjusting position, erase only EoL for rigth-justified - if (x == DISPLAY_RIGHT) x = Display.Width - width - 1; - else if (x == DISPLAY_CENTER) x = (Display.Width - width) / 2; - - // erase if requested - if (attribute & DISPLAY_CLEAR) { - int y_min = max(0, lines[num].y), y_max = max(0, lines[num].y + lines[num].font->Height); - for (int c = (attribute & DISPLAY_ONLY_EOL) ? x : 0; c < Display.Width; c++) - for (int y = y_min; y < y_max; y++) - SSD13x6_DrawPixelFast( &Display, c, y, SSD_COLOR_BLACK ); - } - - SSD13x6_FontDrawString( &Display, x, lines[num].y, text, SSD_COLOR_WHITE ); - - ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", text, num+1, x, attribute); - - // update whole display if requested - SSD13x6_display.dirty = true; - if (attribute & DISPLAY_UPDATE) update(); - - return width + x < Display.Width; -} - -/**************************************************************************************** - * Try to align string for better scrolling visual. there is probably much better to do - */ -static int stretch(int num, char *string, int max) { - char space[] = " "; - int len = strlen(string), extra = 0, boundary; - - num--; - - // we might already fit - SSD13x6_SetFont( &Display, lines[num].font ); - if (SSD13x6_FontMeasureString( &Display, string ) <= Display.Width) return 0; - - // add some space for better visual - strncat(string, space, max-len); - string[max] = '\0'; - len = strlen(string); - - // mark the end of the extended string - boundary = SSD13x6_FontMeasureString( &Display, string ); - - // add a full display width - while (len < max && SSD13x6_FontMeasureString( &Display, string ) - boundary < Display.Width) { - string[len++] = string[extra++]; - string[len] = '\0'; - } - - return boundary; -} - -/**************************************************************************************** - * - */ -static void text(enum display_font_e font, enum display_pos_e pos, int attribute, char *text, ...) { - va_list args; - - TextAnchor Anchor = TextAnchor_Center; - - if (attribute & DISPLAY_CLEAR) SSD13x6_Clear( &Display, SSD_COLOR_BLACK ); - - if (!text) return; - - va_start(args, text); - - switch(font) { - case DISPLAY_FONT_LINE_1: - SSD13x6_SetFont( &Display, &Font_line_1 ); - break; - case DISPLAY_FONT_LINE_2: - SSD13x6_SetFont( &Display, &Font_line_2 ); - break; - case DISPLAY_FONT_SMALL: - SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_11x13 ); - break; - case DISPLAY_FONT_MEDIUM: - case DISPLAY_FONT_DEFAULT: - default: - SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_15x17 ); - break; - case DISPLAY_FONT_LARGE: - SSD13x6_SetFont( &Display, &Font_droid_sans_fallback_24x28 ); - break; - case DISPLAY_FONT_SEGMENT: - if (Display.Height == 32) SSD13x6_SetFont( &Display, &Font_Tarable7Seg_16x32 ); - else SSD13x6_SetFont( &Display, &Font_Tarable7Seg_32x64 ); - break; - } - - switch(pos) { - case DISPLAY_TOP_LEFT: - default: - Anchor = TextAnchor_NorthWest; - break; - case DISPLAY_MIDDLE_LEFT: - Anchor = TextAnchor_West; - break; - case DISPLAY_BOTTOM_LEFT: - Anchor = TextAnchor_SouthWest; - break; - case DISPLAY_CENTERED: - Anchor = TextAnchor_Center; - break; - } - - ESP_LOGD(TAG, "SSDD13x6 displaying %s at %u with attribute %u", text, Anchor, attribute); - - SSD13x6_FontDrawAnchoredString( &Display, Anchor, text, SSD_COLOR_WHITE ); - - SSD13x6_display.dirty = true; - if (attribute & DISPLAY_UPDATE) update(); - - va_end(args); -} - -/**************************************************************************************** - * Process graphic display data from column-oriented data (MSbit first) - */ -static void draw_cbr(u8_t *data, int width, int height) { - if (!height) height = Display.Height; - if (!width) width = Display.Width; - - // need to do row/col swap and bit-reverse - int rows = height / 8; - for (int r = 0; r < rows; r++) { - uint8_t *optr = Display.Framebuffer + r*Display.Width, *iptr = data + r; - for (int c = width; --c >= 0;) { - *optr++ = BitReverseTable256[*iptr];; - iptr += rows; - } - } - - SSD13x6_display.dirty = true; -} - -/**************************************************************************************** - * Process graphic display data MSBit first - * WARNING: this has not been tested yet - */ -static void draw_raw(int x1, int y1, int x2, int y2, bool by_column, bool MSb, u8_t *data) { - // default end point to display size - if (x2 == -1) x2 = Display.Width - 1; - if (y2 == -1) y2 = Display.Height - 1; - - display->dirty = true; - - // not a boundary draw - if (y1 % 8 || y2 % 8 || x1 % 8 | x2 % 8) { - ESP_LOGW(TAG, "can't write on non cols/rows boundaries for now"); - } else { - // set addressing mode to match data - if (by_column) { - // copy the window and do row/col exchange - for (int r = y1/8; r <= y2/8; r++) { - uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r; - for (int c = x1; c <= x2; c++) { - *optr++ = MSb ? BitReverseTable256[*iptr] : *iptr; - iptr += (y2-y1)/8 + 1; - } - } - } else { - // just copy the window inside the frame buffer - for (int r = y1/8; r <= y2/8; r++) { - uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r*(x2-x1+1); - for (int c = x1; c <= x2; c++) *optr++ = *iptr++; - } - } - } -} - -/**************************************************************************************** - * Draw line - */ -static void draw_line( int x1, int y1, int x2, int y2) { - SSD13x6_DrawLine( &Display, x1, y1, x2, y2, SSD_COLOR_WHITE ); - SSD13x6_display.dirty = true; -} - -/**************************************************************************************** - * Draw Box - */ -static void draw_box( int x1, int y1, int x2, int y2, bool fill) { - SSD13x6_DrawBox( &Display, x1, y1, x2, y2, SSD_COLOR_WHITE, fill ); - SSD13x6_display.dirty = true; -} - -/**************************************************************************************** - * Brightness - */ -static void brightness(u8_t level) { - SSD13x6_DisplayOn( &Display ); - SSD13x6_SetContrast( &Display, (uint8_t) level); -} - -/**************************************************************************************** - * Display On/Off - */ -static void on(bool state) { - if (state) SSD13x6_DisplayOn( &Display ); - else SSD13x6_DisplayOff( &Display ); -} - -/**************************************************************************************** - * Update - */ -static void update(void) { - if (SSD13x6_display.dirty) SSD13x6_Update( &Display ); - SSD13x6_display.dirty = false; -} - - - diff --git a/components/display/tarablessd13x6/fonts/LICENSE-apache b/components/display/fonts/LICENSE-apache similarity index 100% rename from components/display/tarablessd13x6/fonts/LICENSE-apache rename to components/display/fonts/LICENSE-apache diff --git a/components/display/tarablessd13x6/fonts/LICENSE-liberation-mono b/components/display/fonts/LICENSE-liberation-mono similarity index 100% rename from components/display/tarablessd13x6/fonts/LICENSE-liberation-mono rename to components/display/fonts/LICENSE-liberation-mono diff --git a/components/display/tarablessd13x6/fonts/font_droid_sans_fallback_11x13.c b/components/display/fonts/font_droid_sans_fallback_11x13.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_droid_sans_fallback_11x13.c rename to components/display/fonts/font_droid_sans_fallback_11x13.c index 957b261e..e398c434 100644 --- a/components/display/tarablessd13x6/fonts/font_droid_sans_fallback_11x13.c +++ b/components/display/fonts/font_droid_sans_fallback_11x13.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Fallback11x13[ ] = { 0x05, 0x00, 0x10, 0xE4, 0x11, 0x00, 0x0E, 0x00, 0x02, 0xE4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_droid_sans_fallback_11x13 = { +const struct GDS_FontDef Font_droid_sans_fallback_11x13 = { Droid_Sans_Fallback11x13, 11, 13, diff --git a/components/display/tarablessd13x6/fonts/font_droid_sans_fallback_15x17.c b/components/display/fonts/font_droid_sans_fallback_15x17.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_droid_sans_fallback_15x17.c rename to components/display/fonts/font_droid_sans_fallback_15x17.c index 17e1b75a..5ccbee9f 100644 --- a/components/display/tarablessd13x6/fonts/font_droid_sans_fallback_15x17.c +++ b/components/display/fonts/font_droid_sans_fallback_15x17.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Fallback15x17[ ] = { 0x07, 0xC0, 0x00, 0x01, 0x00, 0x03, 0x01, 0x10, 0x8C, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_droid_sans_fallback_15x17 = { +const struct GDS_FontDef Font_droid_sans_fallback_15x17 = { Droid_Sans_Fallback15x17, 15, 17, diff --git a/components/display/tarablessd13x6/fonts/font_droid_sans_fallback_24x28.c b/components/display/fonts/font_droid_sans_fallback_24x28.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_droid_sans_fallback_24x28.c rename to components/display/fonts/font_droid_sans_fallback_24x28.c index 5719a0fe..a405e73d 100644 --- a/components/display/tarablessd13x6/fonts/font_droid_sans_fallback_24x28.c +++ b/components/display/fonts/font_droid_sans_fallback_24x28.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Fallback24x28[ ] = { 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x0C, 0xE0, 0xF0, 0x03, 0x0C, 0xE0, 0x80, 0x0F, 0x0E, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x7E, 0x00, 0xE0, 0x80, 0x0F, 0x00, 0xE0, 0xF0, 0x03, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_droid_sans_fallback_24x28 = { +const struct GDS_FontDef Font_droid_sans_fallback_24x28 = { Droid_Sans_Fallback24x28, 24, 28, diff --git a/components/display/tarablessd13x6/fonts/font_droid_sans_mono_13x24.c b/components/display/fonts/font_droid_sans_mono_13x24.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_droid_sans_mono_13x24.c rename to components/display/fonts/font_droid_sans_mono_13x24.c index 95bb2321..58b45ff6 100644 --- a/components/display/tarablessd13x6/fonts/font_droid_sans_mono_13x24.c +++ b/components/display/fonts/font_droid_sans_mono_13x24.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Mono13x24[ ] = { 0x0C, 0x00, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x80, 0x07, 0xC0, 0x00, 0x1E, 0xC0, 0x18, 0xF8, 0xC0, 0x18, 0xC0, 0x7F, 0x00, 0x00, 0x1E, 0x00, 0xC0, 0x07, 0x18, 0xF8, 0x00, 0x18, 0x3E, 0x00, 0x80, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_droid_sans_mono_13x24 = { +const struct GDS_FontDef Font_droid_sans_mono_13x24 = { Droid_Sans_Mono13x24, 13, 24, diff --git a/components/display/tarablessd13x6/fonts/font_droid_sans_mono_16x31.c b/components/display/fonts/font_droid_sans_mono_16x31.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_droid_sans_mono_16x31.c rename to components/display/fonts/font_droid_sans_mono_16x31.c index bcab6249..f58ec5e8 100644 --- a/components/display/tarablessd13x6/fonts/font_droid_sans_mono_16x31.c +++ b/components/display/fonts/font_droid_sans_mono_16x31.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Mono16x31[ ] = { 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x00, 0x78, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x60, 0x00, 0xE0, 0x07, 0x60, 0xE0, 0x00, 0x3F, 0x70, 0xE0, 0x00, 0xFC, 0x3C, 0x40, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0xE0, 0x07, 0x40, 0x00, 0xF8, 0x01, 0xE0, 0x00, 0x3F, 0x00, 0xE0, 0xC0, 0x0F, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_droid_sans_mono_16x31 = { +const struct GDS_FontDef Font_droid_sans_mono_16x31 = { Droid_Sans_Mono16x31, 16, 31, diff --git a/components/display/tarablessd13x6/fonts/font_droid_sans_mono_7x13.c b/components/display/fonts/font_droid_sans_mono_7x13.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_droid_sans_mono_7x13.c rename to components/display/fonts/font_droid_sans_mono_7x13.c index dc84c1d9..413defd3 100644 --- a/components/display/tarablessd13x6/fonts/font_droid_sans_mono_7x13.c +++ b/components/display/fonts/font_droid_sans_mono_7x13.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Droid_Sans_Mono7x13[ ] = { 0x06, 0x00, 0x00, 0x30, 0x10, 0xC4, 0x10, 0x00, 0x0F, 0xC4, 0x01, 0x30, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_droid_sans_mono_7x13 = { +const struct GDS_FontDef Font_droid_sans_mono_7x13 = { Droid_Sans_Mono7x13, 7, 13, diff --git a/components/display/tarablessd13x6/fonts/font_liberation_mono_13x21.c b/components/display/fonts/font_liberation_mono_13x21.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_liberation_mono_13x21.c rename to components/display/fonts/font_liberation_mono_13x21.c index 1cd5b46e..37492693 100644 --- a/components/display/tarablessd13x6/fonts/font_liberation_mono_13x21.c +++ b/components/display/fonts/font_liberation_mono_13x21.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Liberation_Mono13x21[ ] = { 0x0C, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xC0, 0x03, 0x10, 0x00, 0x0F, 0x10, 0x0C, 0x3C, 0x18, 0x00, 0xE0, 0x0D, 0x00, 0x80, 0x07, 0x00, 0xE0, 0x01, 0x0C, 0x3C, 0x00, 0x00, 0x0F, 0x00, 0xC0, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_liberation_mono_13x21 = { +const struct GDS_FontDef Font_liberation_mono_13x21 = { Liberation_Mono13x21, 13, 21, diff --git a/components/display/tarablessd13x6/fonts/font_liberation_mono_17x30.c b/components/display/fonts/font_liberation_mono_17x30.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_liberation_mono_17x30.c rename to components/display/fonts/font_liberation_mono_17x30.c index c44307ef..74d28df3 100644 --- a/components/display/tarablessd13x6/fonts/font_liberation_mono_17x30.c +++ b/components/display/fonts/font_liberation_mono_17x30.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Liberation_Mono17x30[] = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x30, 0x00, 0x3F, 0x00, 0x30, 0x00, 0xFC, 0x01, 0x30, 0x38, 0xE0, 0x07, 0x38, 0x38, 0x00, 0x3F, 0x1C, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xF8, 0x01, 0x38, 0x00, 0x3F, 0x00, 0x38, 0xE0, 0x07, 0x00, 0x38, 0xFC, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_liberation_mono_17x30 = { +const struct GDS_FontDef Font_liberation_mono_17x30 = { Liberation_Mono17x30, 17, 30, diff --git a/components/display/tarablessd13x6/fonts/font_liberation_mono_9x15.c b/components/display/fonts/font_liberation_mono_9x15.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_liberation_mono_9x15.c rename to components/display/fonts/font_liberation_mono_9x15.c index 3d7b1d9d..e8d4be4f 100644 --- a/components/display/tarablessd13x6/fonts/font_liberation_mono_9x15.c +++ b/components/display/fonts/font_liberation_mono_9x15.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Liberation_Mono9x15[ ] = { 0x08, 0x00, 0x00, 0x30, 0x40, 0xC6, 0x41, 0x06, 0x67, 0x00, 0x18, 0x06, 0x07, 0xC6, 0x01, 0x30, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_liberation_mono_9x15 = { +const struct GDS_FontDef Font_liberation_mono_9x15 = { Liberation_Mono9x15, 9, 15, diff --git a/components/display/tarablessd13x6/fonts/font_line_1.c b/components/display/fonts/font_line_1.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_line_1.c rename to components/display/fonts/font_line_1.c index d23345a7..1047bcdf 100644 --- a/components/display/tarablessd13x6/fonts/font_line_1.c +++ b/components/display/fonts/font_line_1.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -214,7 +214,7 @@ static const uint8_t Square721_BT11x14[] = { 0x06, 0x00, 0x00, 0xE8, 0x03, 0xB0, 0x04, 0xA0, 0x04, 0xA0, 0x04, 0xE0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char è }; -const struct SSD13x6_FontDef Font_line_1 = { +const struct GDS_FontDef Font_line_1 = { Square721_BT11x14, 11, 14, diff --git a/components/display/tarablessd13x6/fonts/font_line_2.c b/components/display/fonts/font_line_2.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_line_2.c rename to components/display/fonts/font_line_2.c index 19cc11cf..8d4ab57d 100644 --- a/components/display/tarablessd13x6/fonts/font_line_2.c +++ b/components/display/fonts/font_line_2.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -237,7 +237,7 @@ static const uint8_t Archivo_Narrow18x24[] = { 0x0A, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xE0, 0x38, 0xFF, 0xE0, 0x38, 0xFC, 0xF7, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x3F, 0x38, 0xF0, 0x0F, 0x38, 0xFF, 0x01, 0x00, 0x1F, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char ÿ }; -const struct SSD13x6_FontDef Font_line_2 = { +const struct GDS_FontDef Font_line_2 = { Archivo_Narrow18x24, 18, 24, diff --git a/components/display/tarablessd13x6/fonts/font_tarable7seg_16x32.c b/components/display/fonts/font_tarable7seg_16x32.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_tarable7seg_16x32.c rename to components/display/fonts/font_tarable7seg_16x32.c index d40ed086..9cae1d64 100644 --- a/components/display/tarablessd13x6/fonts/font_tarable7seg_16x32.c +++ b/components/display/fonts/font_tarable7seg_16x32.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -109,7 +109,7 @@ static const uint8_t Tarable7Seg_16x32[ ] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char  }; -const struct SSD13x6_FontDef Font_Tarable7Seg_16x32 = { +const struct GDS_FontDef Font_Tarable7Seg_16x32 = { Tarable7Seg_16x32, 16, 32, diff --git a/components/display/tarablessd13x6/fonts/font_tarable7seg_32x64.c b/components/display/fonts/font_tarable7seg_32x64.c similarity index 99% rename from components/display/tarablessd13x6/fonts/font_tarable7seg_32x64.c rename to components/display/fonts/font_tarable7seg_32x64.c index fc659328..81071e83 100644 --- a/components/display/tarablessd13x6/fonts/font_tarable7seg_32x64.c +++ b/components/display/fonts/font_tarable7seg_32x64.c @@ -1,4 +1,4 @@ -#include +#include //WARNING: This Font Require X-GLCD Lib. // You can not use it with MikroE GLCD Lib. @@ -109,7 +109,7 @@ static const uint8_t Tarable7Seg_32x64[ ] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Code for char  }; -const struct SSD13x6_FontDef Font_Tarable7Seg_32x64 = { +const struct GDS_FontDef Font_Tarable7Seg_32x64 = { Tarable7Seg_32x64, 32, 64, diff --git a/components/display/tarablessd13x6/ifaces/default_if_spi.c b/components/display/tarablessd13x6/ifaces/default_if_spi.c deleted file mode 100644 index 997ff9ad..00000000 --- a/components/display/tarablessd13x6/ifaces/default_if_spi.c +++ /dev/null @@ -1,123 +0,0 @@ - -/** - * Copyright (c) 2017-2018 Tara Keeling - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include -#include -#include -#include -#include -#include -#include -#include "ssd13x6.h" -#include "ssd13x6_default_if.h" - -static const int SSD13x6_SPI_Command_Mode = 0; -static const int SSD13x6_SPI_Data_Mode = 1; - -static spi_host_device_t SPIHost; -static int DCPin; - -static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ); -static bool SPIDefaultWriteCommand( struct SSD13x6_Device* DeviceHandle, SSDCmd Command ); -static bool SPIDefaultWriteData( struct SSD13x6_Device* DeviceHandle, const uint8_t* Data, size_t DataLength ); -static bool SPIDefaultReset( struct SSD13x6_Device* DeviceHandle ); - -bool SSD13x6_SPIMasterInitDefault( int SPI, int DC ) { - SPIHost = SPI; - DCPin = DC; - return true; -} - -bool SSD13x6_SPIMasterAttachDisplayDefault( struct SSD13x6_Device* DeviceHandle, int Model, int Width, int Height, int CSPin, int RSTPin, int Speed ) { - spi_device_interface_config_t SPIDeviceConfig; - spi_device_handle_t SPIDeviceHandle; - - NullCheck( DeviceHandle, return false ); - - if (CSPin >= 0) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false ); - } - - memset( &SPIDeviceConfig, 0, sizeof( spi_device_interface_config_t ) ); - - SPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_8M; - SPIDeviceConfig.spics_io_num = CSPin; - SPIDeviceConfig.queue_size = 1; - - if ( RSTPin >= 0 ) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 0 ), return false ); - } - - ESP_ERROR_CHECK_NONFATAL( spi_bus_add_device( SPIHost, &SPIDeviceConfig, &SPIDeviceHandle ), return false ); - - memset( DeviceHandle, 0, sizeof( struct SSD13x6_Device ) ); - DeviceHandle->Model = Model; - - return SSD13x6_Init_SPI( DeviceHandle, - Width, - Height, - RSTPin, - CSPin, - SPIDeviceHandle, - SPIDefaultWriteCommand, - SPIDefaultWriteData, - SPIDefaultReset - ); -} - -static bool SPIDefaultWriteBytes( spi_device_handle_t SPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) { - spi_transaction_t SPITransaction = { 0 }; - - NullCheck( SPIHandle, return false ); - NullCheck( Data, return false ); - - if ( DataLength > 0 ) { - gpio_set_level( DCPin, WriteMode ); - - SPITransaction.length = DataLength * 8; - SPITransaction.tx_buffer = Data; - - // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes) - ESP_ERROR_CHECK_NONFATAL( spi_device_polling_transmit(SPIHandle, &SPITransaction), return false ); - } - - return true; -} - -static bool SPIDefaultWriteCommand( struct SSD13x6_Device* DeviceHandle, SSDCmd Command ) { - static uint8_t CommandByte = 0; - - NullCheck( DeviceHandle, return false ); - NullCheck( DeviceHandle->SPIHandle, return false ); - - CommandByte = Command; - - return SPIDefaultWriteBytes( DeviceHandle->SPIHandle, SSD13x6_SPI_Command_Mode, &CommandByte, 1 ); -} - -static bool SPIDefaultWriteData( struct SSD13x6_Device* DeviceHandle, const uint8_t* Data, size_t DataLength ) { - NullCheck( DeviceHandle, return false ); - NullCheck( DeviceHandle->SPIHandle, return false ); - - return SPIDefaultWriteBytes( DeviceHandle->SPIHandle, SSD13x6_SPI_Data_Mode, Data, DataLength ); -} - -static bool SPIDefaultReset( struct SSD13x6_Device* DeviceHandle ) { - NullCheck( DeviceHandle, return false ); - - if ( DeviceHandle->RSTPin >= 0 ) { - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DeviceHandle->RSTPin, 0 ), return false ); - vTaskDelay( pdMS_TO_TICKS( 100 ) ); - ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DeviceHandle->RSTPin, 1 ), return false ); - } - - return true; -} - diff --git a/components/display/tarablessd13x6/ssd13x6.c b/components/display/tarablessd13x6/ssd13x6.c deleted file mode 100644 index 0ba7139f..00000000 --- a/components/display/tarablessd13x6/ssd13x6.c +++ /dev/null @@ -1,351 +0,0 @@ -/** - * Copyright (c) 2017-2018 Tara Keeling - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ssd13x6.h" - -#define SHADOW_BUFFER - -// used by both but different -static uint8_t SSDCmd_Set_Display_Start_Line; -static uint8_t SSDCmd_Set_Display_Offset; -static uint8_t SSDCmd_Set_Column_Address; -static uint8_t SSDCmd_Set_Display_CLK; -static uint8_t SSDCmd_Set_Page_Address; - -// misc boundaries -static uint8_t SSD13x6_Max_Col; -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 ); -} - -bool SSD13x6_WriteData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) { - NullCheck( DeviceHandle->WriteData, return false ); - return ( DeviceHandle->WriteData ) ( DeviceHandle, Data, DataLength ); -} - -void SSD13x6_SetMuxRatio( struct SSD13x6_Device* DeviceHandle, uint8_t Ratio ) { - SSD13x6_WriteCommand( DeviceHandle, 0xA8 ); - SSD13x6_WriteCommand( DeviceHandle, Ratio ); -} - -void SSD13x6_SetDisplayOffset( struct SSD13x6_Device* DeviceHandle, uint8_t Offset ) { - SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Offset ); - SSD13x6_WriteCommand( DeviceHandle, Offset ); -} - -void SSD13x6_SetDisplayStartLine( struct SSD13x6_Device* DeviceHandle, int Line ) { - SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Display_Start_Line + ( uint32_t ) ( Line & 0x1F ) ); -} - -void SSD13x6_SetContrast( struct SSD13x6_Device* DeviceHandle, uint8_t Contrast ) { - SSD13x6_WriteCommand( DeviceHandle, 0x81 ); - SSD13x6_WriteCommand( DeviceHandle, Contrast ); -} - -void SSD13x6_EnableDisplayRAM( struct SSD13x6_Device* DeviceHandle ) { - SSD13x6_WriteCommand( DeviceHandle, 0xA4 ); -} - -void SSD13x6_DisableDisplayRAM( struct SSD13x6_Device* DeviceHandle ) { - SSD13x6_WriteCommand( DeviceHandle, 0xA5 ); -} - -void SSD13x6_SetInverted( struct SSD13x6_Device* DeviceHandle, bool Inverted ) { - SSD13x6_WriteCommand( DeviceHandle, Inverted ? 0xA7 : 0xA6 ); -} - -void SSD13x6_SetDisplayClocks( struct SSD13x6_Device* DeviceHandle, uint32_t DisplayClockDivider, uint32_t OSCFrequency ) { - DisplayClockDivider&= 0x0F; - OSCFrequency&= 0x0F; - SSD13x6_WriteCommand( DeviceHandle, SSDCmd_Set_Display_CLK ); - SSD13x6_WriteCommand( DeviceHandle, ( ( OSCFrequency << 4 ) | DisplayClockDivider ) ); -} - -void SSD13x6_DisplayOn( struct SSD13x6_Device* DeviceHandle ) { - SSD13x6_WriteCommand( DeviceHandle, 0xAF ); -} - -void SSD13x6_DisplayOff( struct SSD13x6_Device* DeviceHandle ) { - SSD13x6_WriteCommand( DeviceHandle, 0xAE ); -} - -void SSD132x_ReMap( struct SSD13x6_Device* DeviceHandle ) { - SSD13x6_WriteCommand( DeviceHandle, 0xA0 ); - SSD13x6_WriteCommand( DeviceHandle, DeviceHandle->ReMap ); -} - -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 ); - break; - case SSD1326: - DeviceHandle->ReMap = (AddressMode == AddressMode_Horizontal) ? (DeviceHandle->ReMap & ~0x80) : (DeviceHandle->ReMap | 0x80); - SSD132x_ReMap(DeviceHandle); - break; - } -} - -void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle ) { -#ifdef SHADOW_BUFFER - // not sure the compiler does not have to redo all calculation in for loops, so local it is - int width = DeviceHandle->Width, rows = DeviceHandle->Height / 8; - uint8_t *optr = DeviceHandle->Shadowbuffer, *iptr = DeviceHandle->Framebuffer; - - // by row, find first and last columns that have been updated - for (int r = 0; r < rows; r++) { - uint8_t first = 0, last; - for (int c = 0; c < width; c++) { - if (*iptr != *optr) { - if (!first) first = c + 1; - last = c ; - } - *optr++ = *iptr++; - } - - // now update the display by "byte rows" - if (first--) { - SSD13x6_SetColumnAddress( DeviceHandle, first, last ); - SSD13x6_SetPageAddress( DeviceHandle, r, r); - SSD13x6_WriteData( DeviceHandle, DeviceHandle->Shadowbuffer + r*width + first, last - first + 1); - } - } -#else - if (DeviceHandle->Model == SH1106) { - // SH1106 requires a page-by-page update and has 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 ); - } -#endif -} - -void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) { - NullCheck( Data, return ); - DataLength = DataLength > DeviceHandle->FramebufferSize ? DeviceHandle->FramebufferSize : DataLength; - if ( DataLength > 0 ) SSD13x6_WriteData( DeviceHandle, Data, DataLength ); -} - -void SSD13x6_SetHFlip( struct SSD13x6_Device* DeviceHandle, bool On ) { - switch (DeviceHandle->Model) { - case SH1106: - case SSD1306: - SSD13x6_WriteCommand( DeviceHandle, On ? 0xA1 : 0xA0 ); - break; - case SSD1326: - DeviceHandle->ReMap = On ? (DeviceHandle->ReMap | 0x01) : (DeviceHandle->ReMap & ~0x01); - SSD132x_ReMap(DeviceHandle); - break; - } -} - -void SSD13x6_SetVFlip( struct SSD13x6_Device* DeviceHandle, bool On ) { - switch (DeviceHandle->Model) { - case SH1106: - case SSD1306: - SSD13x6_WriteCommand( DeviceHandle, On ? 0xC8 : 0xC0 ); - break; - case SSD1326: - DeviceHandle->ReMap = On ? (DeviceHandle->ReMap | 0x05) : (DeviceHandle->ReMap & ~0x05); - SSD132x_ReMap( DeviceHandle ); - break; - } -} - -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 ); - - // 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 ) { - NullCheck( DeviceHandle, return ); - - CheckBounds( Start > SSD13x6_Max_Row, return ); - CheckBounds( End > SSD13x6_Max_Row, return ); - - // 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 ); - } -} - -bool SSD13x6_HWReset( struct SSD13x6_Device* DeviceHandle ) { - NullCheck( DeviceHandle, return 0 ); - - if ( DeviceHandle->Reset != NULL ) { - return ( DeviceHandle->Reset ) ( DeviceHandle ); - } - - /* This should always return true if there is no reset callback as - * no error would have occurred during the non existant reset. - */ - return true; -} - -static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int Height ) { - DeviceHandle->Width = Width; - DeviceHandle->Height = Height; - -#ifdef SHADOW_BUFFER - DeviceHandle->Shadowbuffer = heap_caps_malloc( DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); - memset( DeviceHandle->Shadowbuffer, 0xFF, DeviceHandle->FramebufferSize ); -#endif - - SSD13x6_HWReset( DeviceHandle ); - 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; - - if (DeviceHandle->Model == SSD1306) { - // charge pump regulator, do direct init - SSD13x6_WriteCommand( DeviceHandle, 0x8D ); - SSD13x6_WriteCommand( DeviceHandle, 0x14 ); - - // COM pins HW config (alternative:EN if 64, DIS if 32, remap:DIS) - some display might need something difference - SSD13x6_WriteCommand( DeviceHandle, 0xDA ); - SSD13x6_WriteCommand( DeviceHandle, ((Height == 64 ? 1 : 0) << 4) | (0 < 5) ); - - } else { - // 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; - SSDCmd_Set_Column_Address = 0x15; - SSDCmd_Set_Display_CLK = 0xB3; - SSDCmd_Set_Page_Address = 0x75; // not really a page but a row - - SSD13x6_Max_Col = 255; - - // no gray scale - DeviceHandle->ReMap |= 0x10; - SSD132x_ReMap( DeviceHandle ); - } - - SSD13x6_SetMuxRatio( DeviceHandle, Height - 1 ); - SSD13x6_SetDisplayOffset( DeviceHandle, 0x00 ); - 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_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 ); - - return true; -} - -bool SSD13x6_Init_I2C( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int I2CAddress, int ResetPin, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ) { - NullCheck( DeviceHandle, return false ); - NullCheck( WriteCommand, return false ); - NullCheck( WriteData, return false ); - - 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 ); -} - -bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int ResetPin, int CSPin, spi_device_handle_t SPIHandle, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ) { - NullCheck( DeviceHandle, return false ); - NullCheck( WriteCommand, return false ); - NullCheck( WriteData, return false ); - - DeviceHandle->WriteCommand = WriteCommand; - DeviceHandle->WriteData = WriteData; - DeviceHandle->Reset = Reset; - DeviceHandle->SPIHandle = SPIHandle; - DeviceHandle->RSTPin = ResetPin; - DeviceHandle->CSPin = CSPin; - - DeviceHandle->FramebufferSize = ( Width * Height ) / 8; -#ifdef SHADOW_BUFFER - DeviceHandle->Framebuffer = calloc( 1, DeviceHandle->FramebufferSize ); -#else - DeviceHandle->Framebuffer = heap_caps_calloc( 1, DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA ); -#endif - NullCheck( DeviceHandle->Framebuffer, return false ); - - return SSD13x6_Init( DeviceHandle, Width, Height ); -} diff --git a/components/display/tarablessd13x6/ssd13x6.h b/components/display/tarablessd13x6/ssd13x6.h deleted file mode 100644 index 697eb02a..00000000 --- a/components/display/tarablessd13x6/ssd13x6.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _SSD13X6_H_ -#define _SSD13X6_H_ - -/* For uint(X)_t */ -#include - -/* For booooool */ -#include - -#include "sdkconfig.h" -#include "ssd13x6_err.h" - -#define SSD_ALWAYS_INLINE __attribute__( ( always_inline ) ) - -#define CAPS_COLUMN_RANGE 0x01 -#define CAPS_PAGE_RANGE 0x02 -#define CAPS_ADDRESS_VERTICAL 0x04 - -#if ! defined BIT -#define BIT( n ) ( 1 << n ) -#endif - -typedef uint8_t SSDCmd; - -typedef enum { - AddressMode_Horizontal = 0, - AddressMode_Vertical, - AddressMode_Page, - AddressMode_Invalid -} SSD13x6_AddressMode; - -struct SSD13x6_Device; - -/* - * These can optionally return a succeed/fail but are as of yet unused in the driver. - */ -typedef bool ( *WriteCommandProc ) ( struct SSD13x6_Device* DeviceHandle, SSDCmd Command ); -typedef bool ( *WriteDataProc ) ( struct SSD13x6_Device* DeviceHandle, const uint8_t* Data, size_t DataLength ); -typedef bool ( *ResetProc ) ( struct SSD13x6_Device* DeviceHandle ); - -struct spi_device_t; -typedef struct spi_device_t* spi_device_handle_t; - -struct SSD13x6_FontDef; - -struct SSD13x6_Device { - /* I2C Specific */ - int Address; - - /* SPI Specific */ - spi_device_handle_t SPIHandle; - int RSTPin; - int CSPin; - - /* Everything else */ - int Width; - int Height; - - enum { SSD1306, SSD1326, SH1106 } Model; - uint8_t ReMap; - uint8_t* Framebuffer, *Shadowbuffer; - int FramebufferSize; - - WriteCommandProc WriteCommand; - WriteDataProc WriteData; - ResetProc Reset; - - const struct SSD13x6_FontDef* Font; - bool FontForceProportional; - bool FontForceMonospace; -}; - -void SSD13x6_SetMuxRatio( struct SSD13x6_Device* DeviceHandle, uint8_t Ratio ); -void SSD13x6_SetDisplayOffset( struct SSD13x6_Device* DeviceHandle, uint8_t Offset ); -void SSD13x6_SetDisplayStartLines( struct SSD13x6_Device* DeviceHandle ); - -void SSD13x6_SetSegmentRemap( struct SSD13x6_Device* DeviceHandle, bool Remap ); - -void SSD13x6_SetContrast( struct SSD13x6_Device* DeviceHandle, uint8_t Contrast ); -void SSD13x6_EnableDisplayRAM( struct SSD13x6_Device* DeviceHandle ); -void SSD13x6_DisableDisplayRAM( struct SSD13x6_Device* DeviceHandle ); -void SSD13x6_SetInverted( struct SSD13x6_Device* DeviceHandle, bool Inverted ); -void SSD13x6_SetHFlip( struct SSD13x6_Device* DeviceHandle, bool On ); -void SSD13x6_SetVFlip( struct SSD13x6_Device* DeviceHandle, bool On ); -void SSD13x6_DisplayOn( struct SSD13x6_Device* DeviceHandle ); -void SSD13x6_DisplayOff( struct SSD13x6_Device* DeviceHandle ); -void SSD13x6_SetDisplayAddressMode( struct SSD13x6_Device* DeviceHandle, SSD13x6_AddressMode AddressMode ); -void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle ); -void SSD13x6_SetDisplayClocks( struct SSD13x6_Device* DeviceHandle, uint32_t DisplayClockDivider, uint32_t OSCFrequency ); -void SSD13x6_SetColumnAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End ); -void SSD13x6_SetPageAddress( struct SSD13x6_Device* DeviceHandle, uint8_t Start, uint8_t End ); -bool SSD13x6_HWReset( struct SSD13x6_Device* DeviceHandle ); -bool SSD13x6_Init_I2C( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int I2CAddress, int ResetPin, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ); -bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Height, int ResetPin, int CSPin, spi_device_handle_t SPIHandle, WriteCommandProc WriteCommand, WriteDataProc WriteData, ResetProc Reset ); -int SSD13x6_GetCaps( struct SSD13x6_Device* DeviceHandle ); - -void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ); - -#endif diff --git a/components/display/tarablessd13x6/ssd13x6_default_if.h b/components/display/tarablessd13x6/ssd13x6_default_if.h deleted file mode 100644 index c1173e14..00000000 --- a/components/display/tarablessd13x6/ssd13x6_default_if.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _SSD13x6_DEFAULT_IF_H_ -#define _SSD13x6_DEFAULT_IF_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -bool SSD13x6_I2CMasterInitDefault( int PortNumber, int SDA, int SCL ); -bool SSD13x6_I2CMasterAttachDisplayDefault( struct SSD13x6_Device* DisplayHandle, int Model, int Width, int Height, int I2CAddress, int RSTPin ); - -bool SSD13x6_SPIMasterInitDefault( int SPI, int DC); -bool SSD13x6_SPIMasterAttachDisplayDefault( struct SSD13x6_Device* DeviceHandle, int Model, int Width, int Height, int CSPin, int RSTPin, int Speed ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/display/tarablessd13x6/ssd13x6_draw.c b/components/display/tarablessd13x6/ssd13x6_draw.c deleted file mode 100644 index 9a4d9f91..00000000 --- a/components/display/tarablessd13x6/ssd13x6_draw.c +++ /dev/null @@ -1,253 +0,0 @@ -/** - * Copyright (c) 2017-2018 Tara Keeling - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ssd13x6.h" -#include "ssd13x6_draw.h" - -#undef NullCheck -#define NullCheck(X,Y) - -__attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct SSD13x6_Device* DeviceHandle, int x, int y ) { - bool Result = ( - ( x >= 0 ) && - ( x < DeviceHandle->Width ) && - ( y >= 0 ) && - ( y < DeviceHandle->Height ) - ) ? true : false; - -#if CONFIG_SSD13x6_CLIPDEBUG > 0 - if ( Result == false ) { - ClipDebug( x, y ); - } -#endif - - return Result; -} - -__attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b ) { - int Temp = *b; - - *b = *a; - *a = Temp; -} - -inline void IRAM_ATTR SSD13x6_DrawPixelFast( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color ) { - uint32_t YBit = ( Y & 0x07 ); - uint8_t* FBOffset = NULL; - - /* - * We only need to modify the Y coordinate since the pitch - * of the screen is the same as the width. - * Dividing Y by 8 gives us which row the pixel is in but not - * the bit position. - */ - Y>>= 3; - - FBOffset = DeviceHandle->Framebuffer + ( ( Y * DeviceHandle->Width ) + X ); - - if ( Color == SSD_COLOR_XOR ) { - *FBOffset ^= BIT( YBit ); - } else { - *FBOffset = ( Color == SSD_COLOR_WHITE ) ? *FBOffset | BIT( YBit ) : *FBOffset & ~BIT( YBit ); - } -} - -void IRAM_ATTR SSD13x6_DrawPixel( struct SSD13x6_Device* DeviceHandle, int x, int y, int Color ) { - NullCheck( DeviceHandle, return ); - - if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { - SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color ); - } -} - -void IRAM_ATTR SSD13x6_DrawHLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Width, int Color ) { - int XEnd = x + Width; - - NullCheck( DeviceHandle, return ); - NullCheck( DeviceHandle->Framebuffer, return ); - - for ( ; x < XEnd; x++ ) { - if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { - SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color ); - } else { - break; - } - } -} - -void IRAM_ATTR SSD13x6_DrawVLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Height, int Color ) { - int YEnd = y + Height; - - NullCheck( DeviceHandle, return ); - NullCheck( DeviceHandle->Framebuffer, return ); - - for ( ; y < YEnd; y++ ) { - if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { - SSD13x6_DrawPixel( DeviceHandle, x, y, Color ); - } else { - break; - } - } -} - -static inline void IRAM_ATTR DrawWideLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) { - int dx = ( x1 - x0 ); - int dy = ( y1 - y0 ); - int Error = 0; - int Incr = 1; - int x = x0; - int y = y0; - - if ( dy < 0 ) { - Incr = -1; - dy = -dy; - } - - Error = ( dy * 2 ) - dx; - - for ( ; x < x1; x++ ) { - if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { - SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color ); - } - - if ( Error > 0 ) { - Error-= ( dx * 2 ); - y+= Incr; - } - - Error+= ( dy * 2 ); - } -} - -static inline void IRAM_ATTR DrawTallLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) { - int dx = ( x1 - x0 ); - int dy = ( y1 - y0 ); - int Error = 0; - int Incr = 1; - int x = x0; - int y = y0; - - if ( dx < 0 ) { - Incr = -1; - dx = -dx; - } - - Error = ( dx * 2 ) - dy; - - for ( ; y < y1; y++ ) { - if ( IsPixelVisible( DeviceHandle, x, y ) == true ) { - SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color ); - } - - if ( Error > 0 ) { - Error-= ( dy * 2 ); - x+= Incr; - } - - Error+= ( dx * 2 ); - } -} - -void IRAM_ATTR SSD13x6_DrawLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) { - NullCheck( DeviceHandle, return ); - NullCheck( DeviceHandle->Framebuffer, return ); - - if ( x0 == x1 ) { - SSD13x6_DrawVLine( DeviceHandle, x0, y0, ( y1 - y0 ), Color ); - } else if ( y0 == y1 ) { - SSD13x6_DrawHLine( DeviceHandle, x0, y0, ( x1 - x0 ), Color ); - } else { - if ( abs( x1 - x0 ) > abs( y1 - y0 ) ) { - /* Wide ( run > rise ) */ - if ( x0 > x1 ) { - SwapInt( &x0, &x1 ); - SwapInt( &y0, &y1 ); - } - - DrawWideLine( DeviceHandle, x0, y0, x1, y1, Color ); - } else { - /* Tall ( rise > run ) */ - if ( y0 > y1 ) { - SwapInt( &y0, &y1 ); - SwapInt( &x0, &x1 ); - } - - DrawTallLine( DeviceHandle, x0, y0, x1, y1, Color ); - } - } -} - -void IRAM_ATTR SSD13x6_DrawBox( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill ) { - int Width = ( x2 - x1 ); - int Height = ( y2 - y1 ); - - NullCheck( DeviceHandle, return ); - NullCheck( DeviceHandle->Framebuffer, return ); - - if ( Fill == false ) { - /* Top side */ - SSD13x6_DrawHLine( DeviceHandle, x1, y1, Width, Color ); - - /* Bottom side */ - SSD13x6_DrawHLine( DeviceHandle, x1, y1 + Height, Width, Color ); - - /* Left side */ - SSD13x6_DrawVLine( DeviceHandle, x1, y1, Height, Color ); - - /* Right side */ - SSD13x6_DrawVLine( DeviceHandle, x1 + Width, y1, Height, Color ); - } else { - /* Fill the box by drawing horizontal lines */ - for ( ; y1 <= y2; y1++ ) { - SSD13x6_DrawHLine( DeviceHandle, x1, y1, Width, Color ); - } - } -} - -void SSD13x6_Clear( struct SSD13x6_Device* DeviceHandle, int Color ) { - NullCheck( DeviceHandle, return ); - NullCheck( DeviceHandle->Framebuffer, return ); - - memset( DeviceHandle->Framebuffer, Color, DeviceHandle->FramebufferSize ); -} - -void SSD13x6_ClearWindow( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color ) { - NullCheck( DeviceHandle, return ); - NullCheck( DeviceHandle->Framebuffer, return ); - -/* - int xr = ((x1 - 1) / 8) + 1 ) * 8; - int xl = (x2 / 8) * 8; - - for (int y = y1; y <= y2; y++) { - for (int x = x1; x < xr; x++) SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color); - if (xl > xr) memset( DeviceHandle->Framebuffer + (y / 8) * DeviceHandle->Width + xr, 0, xl - xr ); - for (int x = xl; x <= x2; x++) SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color); - } - - return; -*/ - - // cheap optimization on boundaries - if (x1 == 0 && x2 == DeviceHandle->Width - 1 && y1 % 8 == 0 && (y2 + 1) % 8 == 0) { - memset( DeviceHandle->Framebuffer + (y1 / 8) * DeviceHandle->Width, 0, (y2 - y1 + 1) / 8 * DeviceHandle->Width ); - } else { - for (int y = y1; y <= y2; y++) { - for (int x = x1; x <= x2; x++) { - SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color); - } - } - } -} diff --git a/components/display/tarablessd13x6/ssd13x6_draw.h b/components/display/tarablessd13x6/ssd13x6_draw.h deleted file mode 100644 index 63196a40..00000000 --- a/components/display/tarablessd13x6/ssd13x6_draw.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _SSD13x6_DRAW_H_ -#define _SSD13x6_DRAW_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sdkconfig.h" - -#define SSD13x6_CLIPDEBUG_NONE 0 -#define SSD13x6_CLIPDEBUG_WARNING 1 -#define SSD13x6_CLIPDEBUG_ERROR 2 - -#if CONFIG_SSD13x6_CLIPDEBUG == SSD13x6_CLIPDEBUG_NONE - /* - * Clip silently with no console output. - */ - #define ClipDebug( x, y ) -#elif CONFIG_SSD13x6_CLIPDEBUG == SSD13x6_CLIPDEBUG_WARNING - /* - * Log clipping to the console as a warning. - */ - #define ClipDebug( x, y ) { \ - ESP_LOGW( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED", __LINE__, x, y ); \ - } -#elif CONFIG_SSD13x6_CLIPDEBUG == SSD13x6_CLIPDEBUG_ERROR - /* - * Log clipping as an error to the console. - * Also invokes an abort with stack trace. - */ - #define ClipDebug( x, y ) { \ - ESP_LOGE( __FUNCTION__, "Line %d: Pixel at %d, %d CLIPPED, ABORT", __LINE__, x, y ); \ - abort( ); \ - } -#endif - -#define SSD_COLOR_BLACK 0 -#define SSD_COLOR_WHITE 1 -#define SSD_COLOR_XOR 2 - -void SSD13x6_Clear( struct SSD13x6_Device* DeviceHandle, int Color ); -void SSD13x6_ClearWindow( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color ); -void SSD13x6_DrawPixel( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color ); -void SSD13x6_DrawPixelFast( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color ); -void SSD13x6_DrawHLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Width, int Color ); -void SSD13x6_DrawVLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Height, int Color ); -void SSD13x6_DrawLine( struct SSD13x6_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ); -void SSD13x6_DrawBox( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/display/tarablessd13x6/ssd13x6_font.h b/components/display/tarablessd13x6/ssd13x6_font.h deleted file mode 100644 index 300c5efb..00000000 --- a/components/display/tarablessd13x6/ssd13x6_font.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef _SSD13x6_FONT_H_ -#define _SSD13x6_FONT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct SSD13x6_Device; - -/* - * X-GLCD Font format: - * - * First byte of glyph is it's width in pixels. - * Each data byte represents 8 pixels going down from top to bottom. - * - * Example glyph layout for a 16x16 font - * 'a': [Glyph width][Pixel column 0][Pixel column 1] where the number of pixel columns is the font height divided by 8 - * 'b': [Glyph width][Pixel column 0][Pixel column 1]... - * 'c': And so on... - */ - -struct SSD13x6_FontDef { - const uint8_t* FontData; - - int Width; - int Height; - - int StartChar; - int EndChar; - - bool Monospace; -}; - -typedef enum { - TextAnchor_East = 0, - TextAnchor_West, - TextAnchor_North, - TextAnchor_South, - TextAnchor_NorthEast, - TextAnchor_NorthWest, - TextAnchor_SouthEast, - TextAnchor_SouthWest, - TextAnchor_Center -} TextAnchor; - -bool SSD13x6_SetFont( struct SSD13x6_Device* Display, const struct SSD13x6_FontDef* Font ); - -void SSD13x6_FontForceProportional( struct SSD13x6_Device* Display, bool Force ); -void SSD13x6_FontForceMonospace( struct SSD13x6_Device* Display, bool Force ); - -int SSD13x6_FontGetWidth( struct SSD13x6_Device* Display ); -int SSD13x6_FontGetHeight( struct SSD13x6_Device* Display ); - -int SSD13x6_FontGetMaxCharsPerRow( struct SSD13x6_Device* Display ); -int SSD13x6_FontGetMaxCharsPerColumn( struct SSD13x6_Device* Display ); - -int SSD13x6_FontGetCharWidth( struct SSD13x6_Device* Display, char Character ); -int SSD13x6_FontGetCharHeight( struct SSD13x6_Device* Display ); -int SSD13x6_FontMeasureString( struct SSD13x6_Device* Display, const char* Text );\ - -void SSD13x6_FontDrawChar( struct SSD13x6_Device* Display, char Character, int x, int y, int Color ); -void SSD13x6_FontDrawString( struct SSD13x6_Device* Display, int x, int y, const char* Text, int Color ); -void SSD13x6_FontDrawAnchoredString( struct SSD13x6_Device* Display, TextAnchor Anchor, const char* Text, int Color ); -void SSD13x6_FontGetAnchoredStringCoords( struct SSD13x6_Device* Display, int* OutX, int* OutY, TextAnchor Anchor, const char* Text ); - -extern const struct SSD13x6_FontDef Font_droid_sans_fallback_11x13; -extern const struct SSD13x6_FontDef Font_droid_sans_fallback_15x17; -extern const struct SSD13x6_FontDef Font_droid_sans_fallback_24x28; - -extern const struct SSD13x6_FontDef Font_droid_sans_mono_7x13; -extern const struct SSD13x6_FontDef Font_droid_sans_mono_13x24; -extern const struct SSD13x6_FontDef Font_droid_sans_mono_16x31; - -extern const struct SSD13x6_FontDef Font_liberation_mono_9x15; -extern const struct SSD13x6_FontDef Font_liberation_mono_13x21; -extern const struct SSD13x6_FontDef Font_liberation_mono_17x30; - -extern const struct SSD13x6_FontDef Font_Tarable7Seg_16x32; -extern const struct SSD13x6_FontDef Font_Tarable7Seg_32x64; - -extern const struct SSD13x6_FontDef Font_line_1; -extern const struct SSD13x6_FontDef Font_line_2; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/raop/raop.c b/components/raop/raop.c index 55702eb6..07eab618 100644 --- a/components/raop/raop.c +++ b/components/raop/raop.c @@ -415,11 +415,7 @@ static void *rtsp_thread(void *arg) { if (sock != -1) closesocket(sock); #ifndef WIN32 - if (!ctx->joiner) { - LOG_ERROR("We shall not be here %u! %x %x", ctx->running); - } else { - xTaskNotifyGive(ctx->joiner); - } + xTaskNotifyGive(ctx->joiner); vTaskSuspend(NULL); #endif diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c index 4332afcb..3f18cd56 100644 --- a/components/squeezelite/display.c +++ b/components/squeezelite/display.c @@ -23,6 +23,9 @@ #include "squeezelite.h" #include "slimproto.h" #include "display.h" +#include "gds.h" +#include "gds_text.h" +#include "gds_draw.h" #pragma pack(push, 1) @@ -85,8 +88,6 @@ struct ANIC_header { #pragma pack(pop) -extern struct outputstate output; - static struct { TaskHandle_t task; SemaphoreHandle_t mutex; @@ -212,15 +213,15 @@ bool sb_display_init(void) { static EXT_RAM_ATTR StackType_t xStack[SCROLL_STACK_SIZE] __attribute__ ((aligned (4))); // no display, just make sure we won't have requests - if (!display || display->height == 0 || display->width == 0) { + if (!display || GDS_GetWidth(display) <= 0 || GDS_GetHeight(display) <= 0) { LOG_INFO("no display for LMS"); return false; } // need to force height to 32 maximum - displayer.width = display->width; - displayer.height = min(display->height, SB_HEIGHT); - SETD_width = display->width; + displayer.width = GDS_GetWidth(display); + displayer.height = min(GDS_GetHeight(display), SB_HEIGHT); + SETD_width = displayer.width; // create visu configuration visu.bar_gap = 1; @@ -330,8 +331,8 @@ static void send_server(void) { static void server(in_addr_t ip, u16_t hport, u16_t cport) { char msg[32]; sprintf(msg, "%s:%hu", inet_ntoa(ip), hport); - if (displayer.owned) display->text(DISPLAY_FONT_DEFAULT, DISPLAY_CENTERED, DISPLAY_CLEAR | DISPLAY_UPDATE, msg); - SETD_width = display->width; + if (displayer.owned) GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg); + SETD_width = displayer.width; displayer.dirty = true; if (notify_chain) (*notify_chain)(ip, hport, cport); } @@ -426,8 +427,8 @@ static void show_display_buffer(char *ddram) { LOG_DEBUG("\n\t%.40s\n\t%.40s", line1, line2); - display->line(1, DISPLAY_LEFT, DISPLAY_CLEAR, line1); - display->line(2, DISPLAY_LEFT, DISPLAY_CLEAR | DISPLAY_UPDATE, line2); + GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR, line1); + GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, line2); } /**************************************************************************************** @@ -495,13 +496,13 @@ static void grfe_handler( u8_t *data, int len) { if (displayer.owned) { // did we have something that might have write on the bottom of a SB_HEIGHT+ display if (displayer.dirty) { - display->clear(true); + GDS_ClearExt(display, true); displayer.dirty = false; } // draw new frame - display->draw_cbr(data + sizeof(struct grfe_packet), displayer.width, displayer.height); - display->update(); + GDS_DrawBitmapCBR(display, data + sizeof(struct grfe_packet), displayer.width, displayer.height); + GDS_Update(display); } xSemaphoreGive(displayer.mutex); @@ -519,10 +520,10 @@ static void grfb_handler(u8_t *data, int len) { LOG_INFO("brightness %hu", pkt->brightness); if (pkt->brightness < 0) { - display->on(false); + GDS_DisplayOff(display); } else { - display->on(true); - display->brightness(pkt->brightness); + GDS_DisplayOn(display); + GDS_SetContrast(display, pkt->brightness); } } @@ -603,8 +604,8 @@ static void grfg_handler(u8_t *data, int len) { // can only write if we really own display if (displayer.owned) { - display->draw_cbr(scroller.frame, scroller.back.width, displayer.height); - display->update(); + GDS_DrawBitmapCBR(display, scroller.frame, scroller.back.width, displayer.height); + GDS_Update(display); } // now we can active scrolling, but only if we are not on a small screen @@ -703,7 +704,7 @@ static void visu_update(void) { visu_export.level = 0; pthread_mutex_unlock(&visu_export.mutex); - display->clear(false, false, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); + GDS_ClearExt(display, false, false, visu.col, visu.row, visu.col + visu.width - 1, visu.row + visu.height - 1); for (int i = visu.n; --i >= 0;) { int x1 = visu.col + visu.border + visu.bar_border + i*(visu.bar_width + visu.bar_gap); @@ -713,11 +714,11 @@ static void visu_update(void) { else if (visu.bars[i].max) visu.bars[i].max--; for (int j = 0; j <= visu.bars[i].current; j += 2) - display->draw_line( x1, y1 - j, x1 + visu.bar_width - 1, y1 - j); + GDS_DrawLine(display, x1, y1 - j, x1 + visu.bar_width - 1, y1 - j, GDS_COLOR_WHITE); if (visu.bars[i].max > 2) { - display->draw_line( x1, y1 - visu.bars[i].max, x1 + visu.bar_width - 1, y1 - visu.bars[i].max); - display->draw_line( x1, y1 - visu.bars[i].max + 1, x1 + visu.bar_width - 1, y1 - visu.bars[i].max + 1); + GDS_DrawLine(display, x1, y1 - visu.bars[i].max, x1 + visu.bar_width - 1, y1 - visu.bars[i].max, GDS_COLOR_WHITE); + GDS_DrawLine(display, x1, y1 - visu.bars[i].max + 1, x1 + visu.bar_width - 1, y1 - visu.bars[i].max + 1, GDS_COLOR_WHITE); } } } @@ -756,7 +757,7 @@ static void visu_handler( u8_t *data, int len) { visu.mode = pkt->which; // little trick to clean the taller screens when switching visu - if (visu.row >= SB_HEIGHT) display->clear(false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1); + if (visu.row >= SB_HEIGHT) GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1); if (visu.mode) { if (pkt->count >= 4) { @@ -767,17 +768,17 @@ static void visu_handler( u8_t *data, int len) { visu.width = htonl(pkt->width); visu.height = pkt->height ? pkt->height : SB_HEIGHT; - visu.col = pkt->col < 0 ? display->width + pkt->col : pkt->col; - visu.row = pkt->row < 0 ? display->height + pkt->row : pkt->row; + visu.col = pkt->col < 0 ? displayer.width + pkt->col : pkt->col; + visu.row = pkt->row < 0 ? GDS_GetHeight(display) + pkt->row : pkt->row; visu.border = htonl(pkt->border); bars = htonl(pkt->bars); visu.spectrum_scale = htonl(pkt->spectrum_scale) / 100.; } else { // full screen visu, try to use bottom screen if available - visu.width = display->width; - visu.height = display->height > SB_HEIGHT ? display->height - SB_HEIGHT : display->height; + visu.width = displayer.width; + visu.height = GDS_GetHeight(display) > SB_HEIGHT ? GDS_GetHeight(display) - SB_HEIGHT : GDS_GetHeight(display); visu.col = visu.border = 0; - visu.row = display->height - visu.height; + visu.row = GDS_GetHeight(display) - visu.height; bars = htonl(pkt->full.bars); visu.spectrum_scale = htonl(pkt->full.spectrum_scale) / 100.; } @@ -811,7 +812,7 @@ static void visu_handler( u8_t *data, int len) { // reset bars maximum for (int i = visu.n; --i >= 0;) visu.bars[i].max = 0; - display->clear(false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1); + GDS_ClearExt(display, false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1); LOG_INFO("Visualizer with %u bars of width %d:%d:%d:%d (%w:%u,h:%u,c:%u,r:%u,s:%.02f)", visu.n, visu.bar_border, visu.bar_width, visu.bar_gap, visu.border, visu.width, visu.height, visu.col, visu.row, visu.spectrum_scale); } else { @@ -854,7 +855,7 @@ static void displayer_task(void *args) { memcpy(scroller.frame, scroller.back.frame, scroller.back.width * displayer.height / 8); for (int i = 0; i < scroller.width * displayer.height / 8; i++) scroller.frame[i] |= scroller.scroll.frame[scroller.scrolled * displayer.height / 8 + i]; scroller.scrolled += scroller.by; - if (displayer.owned) display->draw_cbr(scroller.frame, scroller.width, displayer.height); + if (displayer.owned) GDS_DrawBitmapCBR(display, scroller.frame, scroller.width, displayer.height); // short sleep & don't need background update scroller.wake = scroller.speed; @@ -884,7 +885,7 @@ static void displayer_task(void *args) { } // need to make sure we own display - if (displayer.owned) display->update(); + if (displayer.owned) GDS_Update(display); // release semaphore and sleep what's needed xSemaphoreGive(displayer.mutex);