From 5a9df7b0d576b33ce21b5c5be153160be8e3aa25 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Sat, 18 Jan 2020 16:19:06 -0800 Subject: [PATCH] refactor display - part of components - separation between LMS & driver - move slimp message to squeezelite --- components/display/component.mk | 13 - components/display/display.c | 119 -------- components/services/buttons.c | 2 +- components/services/buttons.h | 2 +- components/services/component.mk | 3 + components/services/display.c | 58 ++++ components/{display => services}/display.h | 22 +- .../{display => services}/driver_SSD1306.c | 236 +++++--------- .../tarablessd1306/.gitignore | 0 .../tarablessd1306/CMakeLists.txt | 0 .../tarablessd1306/Kconfig | 0 .../tarablessd1306/LICENSE | 0 .../tarablessd1306/README.md | 0 .../tarablessd1306/component.mk | 0 .../tarablessd1306/fonts/LICENSE-apache | 0 .../fonts/LICENSE-liberation-mono | 0 .../fonts/font_droid_sans_fallback_11x13.c | 0 .../fonts/font_droid_sans_fallback_15x17.c | 0 .../fonts/font_droid_sans_fallback_24x28.c | 0 .../fonts/font_droid_sans_mono_13x24.c | 0 .../fonts/font_droid_sans_mono_16x31.c | 0 .../fonts/font_droid_sans_mono_7x13.c | 0 .../fonts/font_liberation_mono_13x21.c | 0 .../fonts/font_liberation_mono_17x30.c | 0 .../fonts/font_liberation_mono_9x15.c | 0 .../fonts/font_tarable7seg_16x32.c | 0 .../fonts/font_tarable7seg_32x64.c | 0 .../tarablessd1306/ifaces/default_if_i2c.c | 0 .../tarablessd1306/ifaces/default_if_spi.c | 0 .../tarablessd1306/ssd1306.c | 0 .../tarablessd1306/ssd1306.h | 0 .../tarablessd1306/ssd1306_default_if.h | 0 .../tarablessd1306/ssd1306_draw.c | 0 .../tarablessd1306/ssd1306_draw.h | 0 .../tarablessd1306/ssd1306_err.h | 0 .../tarablessd1306/ssd1306_font.c | 0 .../tarablessd1306/ssd1306_font.h | 0 components/squeezelite/controls.c | 2 +- components/squeezelite/display.c | 289 ++++++++++++++++++ components/squeezelite/embedded.c | 6 +- plugin/SqueezeESP32/Graphics.pm | 4 + plugin/SqueezeESP32/Text.pm | 3 +- 42 files changed, 443 insertions(+), 316 deletions(-) delete mode 100644 components/display/component.mk delete mode 100644 components/display/display.c create mode 100644 components/services/display.c rename components/{display => services}/display.h (64%) rename components/{display => services}/driver_SSD1306.c (58%) rename components/{display => services}/tarablessd1306/.gitignore (100%) rename components/{display => services}/tarablessd1306/CMakeLists.txt (100%) rename components/{display => services}/tarablessd1306/Kconfig (100%) rename components/{display => services}/tarablessd1306/LICENSE (100%) rename components/{display => services}/tarablessd1306/README.md (100%) rename components/{display => services}/tarablessd1306/component.mk (100%) rename components/{display => services}/tarablessd1306/fonts/LICENSE-apache (100%) rename components/{display => services}/tarablessd1306/fonts/LICENSE-liberation-mono (100%) rename components/{display => services}/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_droid_sans_mono_13x24.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_droid_sans_mono_16x31.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_droid_sans_mono_7x13.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_liberation_mono_13x21.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_liberation_mono_17x30.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_liberation_mono_9x15.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_tarable7seg_16x32.c (100%) rename components/{display => services}/tarablessd1306/fonts/font_tarable7seg_32x64.c (100%) rename components/{display => services}/tarablessd1306/ifaces/default_if_i2c.c (100%) rename components/{display => services}/tarablessd1306/ifaces/default_if_spi.c (100%) rename components/{display => services}/tarablessd1306/ssd1306.c (100%) rename components/{display => services}/tarablessd1306/ssd1306.h (100%) rename components/{display => services}/tarablessd1306/ssd1306_default_if.h (100%) rename components/{display => services}/tarablessd1306/ssd1306_draw.c (100%) rename components/{display => services}/tarablessd1306/ssd1306_draw.h (100%) rename components/{display => services}/tarablessd1306/ssd1306_err.h (100%) rename components/{display => services}/tarablessd1306/ssd1306_font.c (100%) rename components/{display => services}/tarablessd1306/ssd1306_font.h (100%) create mode 100644 components/squeezelite/display.c diff --git a/components/display/component.mk b/components/display/component.mk deleted file mode 100644 index 996021a1..00000000 --- a/components/display/component.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# -CFLAGS += -I$(COMPONENT_PATH)/../squeezelite -COMPONENT_SRCDIRS := . tarablessd1306 tarablessd1306/fonts tarablessd1306/ifaces -COMPONENT_ADD_INCLUDEDIRS := . -COMPONENT_ADD_INCLUDEDIRS += ./tarablessd1306 - diff --git a/components/display/display.c b/components/display/display.c deleted file mode 100644 index 4a9fed68..00000000 --- a/components/display/display.c +++ /dev/null @@ -1,119 +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 "config.h" -#include "embedded.h" -#include "display.h" - -static const char *TAG = "display"; - -static bool (*slimp_handler_chain)(u8_t *data, int len); -static struct display_handle_s *handle; -static void (*chained_notify)(in_addr_t ip, u16_t hport, u16_t cport); - -static void server_attach(in_addr_t ip, u16_t hport, u16_t cport); -static bool display_handler(u8_t *data, int len); - -/* scrolling undocumented information - grfs - B: screen number - B:1 = left, 2 = right, - Q: scroll pause once done (ms) - Q: scroll speed (ms) - W: # of pixels to scroll each time - W: 0 = continue scrolling after pause, 1 = scroll to scrollend and then stop, 2 = scroll to scrollend and then end animation (causing new update) - W: width of total scroll area in pixels - - grfd - W: screen number - W: width of scrollable area in pixels - -ANIC flags -ANIM_TRANSITION 0x01 # A transition animation has finished -ANIM_SCROLL_ONCE 0x02 # A scrollonce has finished -ANIM_SCREEN_1 0x04 # For scrollonce only, screen 1 was scrolling -ANIM_SCREEN_2 0x08 # For scrollonce only, screen 2 was scrolling -*/ - -/**************************************************************************************** - * - */ -void display_init(char *welcome) { - char *item = config_alloc_get(NVS_TYPE_STR, "display_config"); - - if (item && *item) { - char * drivername=strstr(item,"driver"); - if (!drivername || (drivername && strcasestr(drivername,"SSD1306"))) { - handle = &SSD1306_handle; - if (handle->init(item, welcome)) { - slimp_handler_chain = slimp_handler; - slimp_handler = display_handler; - ESP_LOGI(TAG, "Display initialization successful"); - } else { - ESP_LOGE(TAG, "Display initialization failed"); - } - } else { - ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item); - } - } else { - ESP_LOGW(TAG, "no display"); - } - - chained_notify = server_notify; - server_notify = server_attach; - - if (item) free(item); -} - -/**************************************************************************************** - * - */ -static void server_attach(in_addr_t ip, u16_t hport, u16_t cport) { - char msg[32]; - sprintf(msg, "%s:%hu", inet_ntoa(ip), hport); - handle->print_message(msg); - if (chained_notify) (*chained_notify)(ip, hport, cport); -} - -/**************************************************************************************** - * Process graphic display data - */ -static bool display_handler(u8_t *data, int len){ - bool res = true; - - if (!strncmp((char*) data, "vfdc", 4)) { - handle->vfdc_handler(data, len); - } else if (!strncmp((char*) data, "grfe", 4)) { - handle->grfe_handler(data, len); - } else if (!strncmp((char*) data, "grfb", 4)) { - handle->grfb_handler(data, len); - } else { - res = false; - } - - // chain protocol handlers (bitwise or is fine) - if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len); - return res; -} - diff --git a/components/services/buttons.c b/components/services/buttons.c index a5fe9a44..4b260b98 100644 --- a/components/services/buttons.c +++ b/components/services/buttons.c @@ -218,7 +218,7 @@ void button_create(void *client, int gpio, int type, bool pull, int debounce, bu /**************************************************************************************** * Get stored id */ - void button_get_client(int gpio) { +void *button_get_client(int gpio) { for (int i = 0; i < n_buttons; i++) { if (buttons[i].gpio == gpio) return buttons[i].client; } diff --git a/components/services/buttons.h b/components/services/buttons.h index e626bf66..907b0e67 100644 --- a/components/services/buttons.h +++ b/components/services/buttons.h @@ -35,4 +35,4 @@ NOTE: shifter buttons *must* be created before shiftee void button_create(void *client, int gpio, int type, bool pull, int debounce, button_handler handler, int long_press, int shifter_gpio); void *button_remap(void *client, int gpio, button_handler handler, int long_press, int shifter_gpio); -void button_get_client(int gpio); +void *button_get_client(int gpio); diff --git a/components/services/component.mk b/components/services/component.mk index e0e9f4c1..5bdf84c6 100644 --- a/components/services/component.mk +++ b/components/services/component.mk @@ -7,4 +7,7 @@ # please read the SDK documents if you need to do this. # +COMPONENT_SRCDIRS := . tarablessd1306 tarablessd1306/fonts tarablessd1306/ifaces COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_ADD_INCLUDEDIRS += ./tarablessd1306 diff --git a/components/services/display.c b/components/services/display.c new file mode 100644 index 00000000..da3c472c --- /dev/null +++ b/components/services/display.c @@ -0,0 +1,58 @@ +/* + * (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 "config.h" +#include "display.h" + +// here we should include all possible drivers +extern struct display_s SSD1306_display; + +struct display_s *display; + +static const char *TAG = "display"; + +/**************************************************************************************** + * + */ +void display_init(char *welcome) { + char *item = config_alloc_get(NVS_TYPE_STR, "display_config"); + + if (item && *item) { + char * drivername=strstr(item,"driver"); + if (!drivername || (drivername && strcasestr(drivername,"SSD1306"))) { + display = &SSD1306_display; + if (display->init(item, welcome)) { + ESP_LOGI(TAG, "Display initialization successful"); + } else { + ESP_LOGE(TAG, "Display initialization failed"); + } + } else { + ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item); + } + } else { + ESP_LOGW(TAG, "no display"); + } + + if (item) free(item); +} diff --git a/components/display/display.h b/components/services/display.h similarity index 64% rename from components/display/display.h rename to components/services/display.h index a2ea64ca..138af82f 100644 --- a/components/display/display.h +++ b/components/services/display.h @@ -18,16 +18,16 @@ #pragma once -struct display_handle_s { - bool (*init)(char *config, char* welcome); - void (*print_message)(char *msg); - void (*vfdc_handler)(u8_t *data, int len); - void (*grfe_handler)(u8_t *data, int len); - void (*grfb_handler)(u8_t *data, int len); - void (*visu_handler)(u8_t *data, int len); -}; - -extern struct display_handle_s SSD1306_handle; - +#define DISPLAY_CLEAR 0x01 +#define DISPLAY_UPDATE 0x02 +enum display_pos_e { DISPLAY_TOP_LEFT, DISPLAY_MIDDLE_LEFT, DISPLAY_BOTTOM_LEFT, DISPLAY_CENTER }; +extern struct display_s { + bool (*init)(char *config, char *welcome); + void (*on)(bool state); + void (*brightness)(u8_t level); + void (*text)(enum display_pos_e pos, int attribute, char *msg); + void (*update)(void); + void (*v_draw)(u8_t *data); +} *display; \ No newline at end of file diff --git a/components/display/driver_SSD1306.c b/components/services/driver_SSD1306.c similarity index 58% rename from components/display/driver_SSD1306.c rename to components/services/driver_SSD1306.c index aa2d7290..e7c32c45 100644 --- a/components/display/driver_SSD1306.c +++ b/components/services/driver_SSD1306.c @@ -31,24 +31,21 @@ #include "ssd1306_default_if.h" #define I2C_ADDRESS 0x3C -#define LINELEN 40 + static const char *TAG = "display"; -static void vfdc_handler( u8_t *_data, int bytes_read); -static void grfe_handler( u8_t *data, int len); -static void grfb_handler( u8_t *data, int len); -static bool display_init(char *config, char *welcome); -static void print_message(char *msg); +// handlers +static bool init(char *config, char *welcome); +static void text(enum display_pos_e pos, int attribute, char *text); +static void v_draw(u8_t *data); +static void brightness(u8_t level); +static void on(bool state); +static void update(void); -struct display_handle_s SSD1306_handle = { - display_init, - print_message, - vfdc_handler, - grfe_handler, - grfb_handler, - NULL, NULL, -}; +// display structure for others to use +struct display_s SSD1306_display = { init, on, brightness, text, update, v_draw, NULL }; +// SSD1306 specific function static struct SSD1306_Device Display; static SSD1306_AddressMode AddressMode = AddressMode_Invalid; @@ -75,11 +72,11 @@ static const unsigned char BitReverseTable256[] = /**************************************************************************************** * */ -static bool display_init(char *config, char *welcome) { +static bool init(char *config, char *welcome) { bool res = false; if (strstr(config, "I2C")) { - int width = -1, height = -1, address=I2C_ADDRESS; + int width = -1, height = -1, address = I2C_ADDRESS; char *p; ESP_LOGI(TAG, "Initializing I2C display with config: %s",config); // no time for smart parsing - this is for tinkerers @@ -87,14 +84,13 @@ static bool display_init(char *config, char *welcome) { if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1); - if (width != -1 && height != -1) { SSD1306_I2CMasterInitDefault( i2c_system_port, -1, -1 ) ; SSD1306_I2CMasterAttachDisplayDefault( &Display, width, height, address, -1 ); SSD1306_SetHFlip( &Display, strcasestr(config, "HFlip") ? true : false); SSD1306_SetVFlip( &Display, strcasestr(config, "VFlip") ? true : false); SSD1306_SetFont( &Display, &Font_droid_sans_fallback_15x17 ); - print_message(welcome); + text(DISPLAY_CENTER, DISPLAY_CLEAR | DISPLAY_UPDATE, welcome); ESP_LOGI(TAG, "Initialized I2C display %dx%d", width, height); res = true; } else { @@ -110,165 +106,62 @@ static bool display_init(char *config, char *welcome) { /**************************************************************************************** * */ -static void print_message(char *msg) { - if (!msg) return; - SSD1306_AddressMode Mode = AddressMode; - SSD1306_Clear( &Display, SSD_COLOR_BLACK ); - SSD1306_SetDisplayAddressMode( &Display, AddressMode_Horizontal ); - SSD1306_FontDrawAnchoredString( &Display, TextAnchor_Center, msg, SSD_COLOR_WHITE ); - SSD1306_Update( &Display ); - SSD1306_SetDisplayAddressMode( &Display, Mode ); -} +static void text(enum display_pos_e pos, int attribute, char *text) { + TextAnchor Anchor = TextAnchor_Center; + + if (attribute & DISPLAY_CLEAR) SSD1306_Clear( &Display, SSD_COLOR_BLACK ); + + if (!text) return; + + switch(pos) { + case DISPLAY_TOP_LEFT: + Anchor = TextAnchor_NorthWest; + break; + case DISPLAY_MIDDLE_LEFT: + break; + case DISPLAY_BOTTOM_LEFT: + Anchor = TextAnchor_SouthWest; + break; + case DISPLAY_CENTER: + Anchor = TextAnchor_Center; + break; + } + + ESP_LOGD(TAG, "SSDD1306 displaying %s at %u with attribute %u", text, Anchor, attribute); -/**************************************************************************************** - * Change special LCD chars to something more printable on screen - */ -static void makeprintable(unsigned char * line) { - for (int n = 0; n < LINELEN; n++) { - switch (line[n]) { - case 11: /* block */ - line[n] = '#'; - break;; - case 16: /* rightarrow */ - line[n] = '>'; - break;; - case 22: /* circle */ - line[n] = '@'; - break;; - case 145: /* note */ - line[n] = ' '; - break;; - case 152: /* bell */ - line[n] = 'o'; - break; - default: - break; - } - } -} - -/**************************************************************************************** - * Check if char is printable, or a valid symbol - */ -static bool charisok(unsigned char c) { - switch (c) { - case 11: /* block */ - case 16: /* rightarrow */ - case 22: /* circle */ - case 145: /* note */ - case 152: /* bell */ - return true; - break;; - default: - return isprint(c); - } -} - -/**************************************************************************************** - * Show the display (text mode) - */ -static void show_display_buffer(char *ddram) { - char line1[LINELEN+1]; - char *line2; - - memset(line1, 0, LINELEN+1); - strncpy(line1, ddram, LINELEN); - line2 = &(ddram[LINELEN]); - line2[LINELEN] = '\0'; - - /* Convert special LCD chars */ - makeprintable((unsigned char *)line1); - makeprintable((unsigned char *)line2); - - ESP_LOGI(TAG, "\n\t%.40s\n\t%.40s", line1, line2); - - SSD1306_Clear( &Display, SSD_COLOR_BLACK ); - SSD1306_FontDrawAnchoredString( &Display, TextAnchor_NorthWest, line1, SSD_COLOR_WHITE ); - SSD1306_FontDrawAnchoredString( &Display, TextAnchor_SouthWest, line2, SSD_COLOR_WHITE ); - - // check addressing mode by rows if (AddressMode != AddressMode_Horizontal) { AddressMode = AddressMode_Horizontal; SSD1306_SetDisplayAddressMode( &Display, AddressMode ); - } - - SSD1306_Update( &Display ); -} - -/**************************************************************************************** - * Process display data - */ -static void vfdc_handler( u8_t *_data, int bytes_read) { - unsigned short *data = (unsigned short*) _data, *display_data; - char ddram[(LINELEN + 1) * 2]; - int n, addr = 0; /* counter */ - - bytes_read -= 4; - if (bytes_read % 2) bytes_read--; /* even number of bytes */ - // if we use Noritake VFD codes, display data starts at 12 - display_data = &(data[5]); /* display data starts at byte 10 */ - - memset(ddram, ' ', LINELEN * 2); - - for (n = 0; n < (bytes_read/2); n++) { - unsigned short d; /* data element */ - unsigned char t, c; - - d = ntohs(display_data[n]); - t = (d & 0x00ff00) >> 8; /* type of display data */ - c = (d & 0x0000ff); /* character/command */ - switch (t) { - case 0x03: /* character */ - if (!charisok(c)) c = ' '; - if (addr <= LINELEN * 2) { - ddram[addr++] = c; - } - break; - case 0x02: /* command */ - switch (c) { - case 0x06: /* display clear */ - memset(ddram, ' ', LINELEN * 2); - break; - case 0x02: /* cursor home */ - addr = 0; - break; - case 0xc0: /* cursor home2 */ - addr = LINELEN; - break; - } - } - } - - show_display_buffer(ddram); + } + SSD1306_FontDrawAnchoredString( &Display, Anchor, text, SSD_COLOR_WHITE ); + if (attribute & DISPLAY_UPDATE) SSD1306_Update( &Display ); } /**************************************************************************************** * Process graphic display data */ -static void grfe_handler( u8_t *data, int len) { - data += 8; - len -= 8; - +static void v_draw( u8_t *data) { #ifndef FULL_REFRESH - // force addressing mode by lines + // force addressing mode by rows if (AddressMode != AddressMode_Horizontal) { AddressMode = AddressMode_Horizontal; SSD1306_SetDisplayAddressMode( &Display, AddressMode ); - } - + } + // try to minimize I2C traffic which is very slow int rows = (Display.Height > 32) ? 4 : Display.Height / 8; for (int r = 0; r < rows; r++) { uint8_t first = 0, last; uint8_t *optr = Display.Framebuffer + r*Display.Width, *iptr = data + r; - // row/col swap, frame buffr comparison and bit-reversing + // row/col swap, frame buffer comparison and bit-reversing for (int c = 0; c < Display.Width; c++) { + *iptr = BitReverseTable256[*iptr]; if (*iptr != *optr) { - if (first) last = c; - else first = c + 1; + if (!first) first = c + 1; + last = c ; } - *optr++ = BitReverseTable256[*iptr]; + *optr++ = *iptr; iptr += rows; } @@ -280,9 +173,12 @@ static void grfe_handler( u8_t *data, int len) { } } #else + int len = (Display.Width * Display.Height) / 8; + // to be verified, but this is as fast as using a pointer on data for (int i = len - 1; i >= 0; i--) data[i] = BitReverseTable256[data[i]]; + // 64 pixels display are not handled by LMS (bitmap is 32 pixels) if (Display.Height > 32) SSD1306_SetPageAddress( &Display, 0, 32/8-1); // force addressing mode by columns @@ -296,18 +192,26 @@ static void grfe_handler( u8_t *data, int len) { } /**************************************************************************************** - * Process graphic display data + * Brightness */ -static void grfb_handler(u8_t *data, int len) { - s16_t brightness = htons(*(uint16_t*) (data + 4)); - - ESP_LOGI(TAG, "brightness %hx", brightness); - if (brightness < 0) { - SSD1306_DisplayOff( &Display ); - } else { - SSD1306_DisplayOn( &Display ); - SSD1306_SetContrast( &Display, brightness * 256 / 4 - 1); - } +static void brightness(u8_t level) { + SSD1306_DisplayOn( &Display ); + SSD1306_SetContrast( &Display, (uint8_t) level); +} + +/**************************************************************************************** + * Display On/Off + */ +static void on(bool state) { + if (state) SSD1306_DisplayOn( &Display ); + else SSD1306_DisplayOff( &Display ); +} + +/**************************************************************************************** + * Update + */ +static void update(void) { + SSD1306_Update( &Display ); } diff --git a/components/display/tarablessd1306/.gitignore b/components/services/tarablessd1306/.gitignore similarity index 100% rename from components/display/tarablessd1306/.gitignore rename to components/services/tarablessd1306/.gitignore diff --git a/components/display/tarablessd1306/CMakeLists.txt b/components/services/tarablessd1306/CMakeLists.txt similarity index 100% rename from components/display/tarablessd1306/CMakeLists.txt rename to components/services/tarablessd1306/CMakeLists.txt diff --git a/components/display/tarablessd1306/Kconfig b/components/services/tarablessd1306/Kconfig similarity index 100% rename from components/display/tarablessd1306/Kconfig rename to components/services/tarablessd1306/Kconfig diff --git a/components/display/tarablessd1306/LICENSE b/components/services/tarablessd1306/LICENSE similarity index 100% rename from components/display/tarablessd1306/LICENSE rename to components/services/tarablessd1306/LICENSE diff --git a/components/display/tarablessd1306/README.md b/components/services/tarablessd1306/README.md similarity index 100% rename from components/display/tarablessd1306/README.md rename to components/services/tarablessd1306/README.md diff --git a/components/display/tarablessd1306/component.mk b/components/services/tarablessd1306/component.mk similarity index 100% rename from components/display/tarablessd1306/component.mk rename to components/services/tarablessd1306/component.mk diff --git a/components/display/tarablessd1306/fonts/LICENSE-apache b/components/services/tarablessd1306/fonts/LICENSE-apache similarity index 100% rename from components/display/tarablessd1306/fonts/LICENSE-apache rename to components/services/tarablessd1306/fonts/LICENSE-apache diff --git a/components/display/tarablessd1306/fonts/LICENSE-liberation-mono b/components/services/tarablessd1306/fonts/LICENSE-liberation-mono similarity index 100% rename from components/display/tarablessd1306/fonts/LICENSE-liberation-mono rename to components/services/tarablessd1306/fonts/LICENSE-liberation-mono diff --git a/components/display/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c b/components/services/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c rename to components/services/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c diff --git a/components/display/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c b/components/services/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c rename to components/services/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c diff --git a/components/display/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c b/components/services/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c rename to components/services/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c diff --git a/components/display/tarablessd1306/fonts/font_droid_sans_mono_13x24.c b/components/services/tarablessd1306/fonts/font_droid_sans_mono_13x24.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_droid_sans_mono_13x24.c rename to components/services/tarablessd1306/fonts/font_droid_sans_mono_13x24.c diff --git a/components/display/tarablessd1306/fonts/font_droid_sans_mono_16x31.c b/components/services/tarablessd1306/fonts/font_droid_sans_mono_16x31.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_droid_sans_mono_16x31.c rename to components/services/tarablessd1306/fonts/font_droid_sans_mono_16x31.c diff --git a/components/display/tarablessd1306/fonts/font_droid_sans_mono_7x13.c b/components/services/tarablessd1306/fonts/font_droid_sans_mono_7x13.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_droid_sans_mono_7x13.c rename to components/services/tarablessd1306/fonts/font_droid_sans_mono_7x13.c diff --git a/components/display/tarablessd1306/fonts/font_liberation_mono_13x21.c b/components/services/tarablessd1306/fonts/font_liberation_mono_13x21.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_liberation_mono_13x21.c rename to components/services/tarablessd1306/fonts/font_liberation_mono_13x21.c diff --git a/components/display/tarablessd1306/fonts/font_liberation_mono_17x30.c b/components/services/tarablessd1306/fonts/font_liberation_mono_17x30.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_liberation_mono_17x30.c rename to components/services/tarablessd1306/fonts/font_liberation_mono_17x30.c diff --git a/components/display/tarablessd1306/fonts/font_liberation_mono_9x15.c b/components/services/tarablessd1306/fonts/font_liberation_mono_9x15.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_liberation_mono_9x15.c rename to components/services/tarablessd1306/fonts/font_liberation_mono_9x15.c diff --git a/components/display/tarablessd1306/fonts/font_tarable7seg_16x32.c b/components/services/tarablessd1306/fonts/font_tarable7seg_16x32.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_tarable7seg_16x32.c rename to components/services/tarablessd1306/fonts/font_tarable7seg_16x32.c diff --git a/components/display/tarablessd1306/fonts/font_tarable7seg_32x64.c b/components/services/tarablessd1306/fonts/font_tarable7seg_32x64.c similarity index 100% rename from components/display/tarablessd1306/fonts/font_tarable7seg_32x64.c rename to components/services/tarablessd1306/fonts/font_tarable7seg_32x64.c diff --git a/components/display/tarablessd1306/ifaces/default_if_i2c.c b/components/services/tarablessd1306/ifaces/default_if_i2c.c similarity index 100% rename from components/display/tarablessd1306/ifaces/default_if_i2c.c rename to components/services/tarablessd1306/ifaces/default_if_i2c.c diff --git a/components/display/tarablessd1306/ifaces/default_if_spi.c b/components/services/tarablessd1306/ifaces/default_if_spi.c similarity index 100% rename from components/display/tarablessd1306/ifaces/default_if_spi.c rename to components/services/tarablessd1306/ifaces/default_if_spi.c diff --git a/components/display/tarablessd1306/ssd1306.c b/components/services/tarablessd1306/ssd1306.c similarity index 100% rename from components/display/tarablessd1306/ssd1306.c rename to components/services/tarablessd1306/ssd1306.c diff --git a/components/display/tarablessd1306/ssd1306.h b/components/services/tarablessd1306/ssd1306.h similarity index 100% rename from components/display/tarablessd1306/ssd1306.h rename to components/services/tarablessd1306/ssd1306.h diff --git a/components/display/tarablessd1306/ssd1306_default_if.h b/components/services/tarablessd1306/ssd1306_default_if.h similarity index 100% rename from components/display/tarablessd1306/ssd1306_default_if.h rename to components/services/tarablessd1306/ssd1306_default_if.h diff --git a/components/display/tarablessd1306/ssd1306_draw.c b/components/services/tarablessd1306/ssd1306_draw.c similarity index 100% rename from components/display/tarablessd1306/ssd1306_draw.c rename to components/services/tarablessd1306/ssd1306_draw.c diff --git a/components/display/tarablessd1306/ssd1306_draw.h b/components/services/tarablessd1306/ssd1306_draw.h similarity index 100% rename from components/display/tarablessd1306/ssd1306_draw.h rename to components/services/tarablessd1306/ssd1306_draw.h diff --git a/components/display/tarablessd1306/ssd1306_err.h b/components/services/tarablessd1306/ssd1306_err.h similarity index 100% rename from components/display/tarablessd1306/ssd1306_err.h rename to components/services/tarablessd1306/ssd1306_err.h diff --git a/components/display/tarablessd1306/ssd1306_font.c b/components/services/tarablessd1306/ssd1306_font.c similarity index 100% rename from components/display/tarablessd1306/ssd1306_font.c rename to components/services/tarablessd1306/ssd1306_font.c diff --git a/components/display/tarablessd1306/ssd1306_font.h b/components/services/tarablessd1306/ssd1306_font.h similarity index 100% rename from components/display/tarablessd1306/ssd1306_font.h rename to components/services/tarablessd1306/ssd1306_font.h diff --git a/components/squeezelite/controls.c b/components/squeezelite/controls.c index 236b1cc1..27bf1978 100644 --- a/components/squeezelite/controls.c +++ b/components/squeezelite/controls.c @@ -142,7 +142,7 @@ static void notify(in_addr_t ip, u16_t hport, u16_t cport) { /**************************************************************************************** * Initialize controls - shall be called once from output_init_embedded */ -void cli_controls_init(void) { +void sb_controls_init(void) { LOG_INFO("initializing CLI controls"); get_mac(mac); actrls_set_default(LMS_controls, NULL); diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c new file mode 100644 index 00000000..e578e429 --- /dev/null +++ b/components/squeezelite/display.c @@ -0,0 +1,289 @@ +/* + * (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 "squeezelite.h" +#include "display.h" + +struct grfb_packet { + char opcode[4]; + u16_t brightness; +}; + +struct grfe_packet { + char opcode[4]; + u16_t offset; + u8_t transition; + u8_t param; +}; + +struct grfs_packet { + char opcode[4]; + u8_t screen; + u8_t direction; // 1=left, 2=right + u32_t pause; // in ms + u32_t speed; // in ms + u16_t by; // # of pixel of scroll step + u16_t mode; // 0=continuous, 1=once and stop, 2=once and end + u16_t width; // total width of animation + u16_t offset; // offset if multiple packets are sent +}; + +struct grfg_packet { + char opcode[4]; + u16_t screen; + u16_t width; // # of pixels of scrollable +}; + +#define LINELEN 40 + +static log_level loglevel = lINFO; + +static bool (*slimp_handler_chain)(u8_t *data, int len); +static void (*notify_chain)(in_addr_t ip, u16_t hport, u16_t cport); + +static void server(in_addr_t ip, u16_t hport, u16_t cport); +static bool handler(u8_t *data, int len); +static void vfdc_handler( u8_t *_data, int bytes_read); +static void grfe_handler( u8_t *data, int len); +static void grfb_handler(u8_t *data, int len); +static void grfs_handler(u8_t *data, int len); +static void grfg_handler(u8_t *data, int len); + +/* scrolling undocumented information + grfs + B: screen number + B:1 = left, 2 = right, + Q: scroll pause once done (ms) + Q: scroll speed (ms) + W: # of pixels to scroll each time + W: 0 = continue scrolling after pause, 1 = scroll to scrollend and then stop, 2 = scroll to scrollend and then end animation (causing new update) + W: width of total scroll area in pixels + + grfd + W: screen number + W: width of scrollable area in pixels + +ANIC flags +ANIM_TRANSITION 0x01 # A transition animation has finished +ANIM_SCROLL_ONCE 0x02 # A scrollonce has finished +ANIM_SCREEN_1 0x04 # For scrollonce only, screen 1 was scrolling +ANIM_SCREEN_2 0x08 # For scrollonce only, screen 2 was scrolling +*/ + +/**************************************************************************************** + * + */ +void sb_display_init(void) { + + slimp_handler_chain = slimp_handler; + slimp_handler = handler; + + notify_chain = server_notify; + server_notify = server; +} + +/**************************************************************************************** + * + */ +static void server(in_addr_t ip, u16_t hport, u16_t cport) { + char msg[32]; + sprintf(msg, "%s:%hu", inet_ntoa(ip), hport); + display->text(DISPLAY_CENTER, DISPLAY_CLEAR | DISPLAY_UPDATE, msg); + if (notify_chain) (*notify_chain)(ip, hport, cport); +} + +/**************************************************************************************** + * Process graphic display data + */ +static bool handler(u8_t *data, int len){ + bool res = true; + + if (!strncmp((char*) data, "vfdc", 4)) { + vfdc_handler(data, len); + } else if (!strncmp((char*) data, "grfe", 4)) { + grfe_handler(data, len); + } else if (!strncmp((char*) data, "grfb", 4)) { + grfb_handler(data, len); + } else if (!strncmp((char*) data, "grfs", 4)) { + grfs_handler(data, len); + } else if (!strncmp((char*) data, "grfg", 4)) { + grfg_handler(data, len); + } else { + res = false; + } + + // chain protocol handlers (bitwise or is fine) + if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len); + return res; +} + +/**************************************************************************************** + * Change special LCD chars to something more printable on screen + */ +static void makeprintable(unsigned char * line) { + for (int n = 0; n < LINELEN; n++) { + switch (line[n]) { + case 11: /* block */ + line[n] = '#'; + break;; + case 16: /* rightarrow */ + line[n] = '>'; + break;; + case 22: /* circle */ + line[n] = '@'; + break;; + case 145: /* note */ + line[n] = ' '; + break;; + case 152: /* bell */ + line[n] = 'o'; + break; + default: + break; + } + } +} + +/**************************************************************************************** + * Check if char is printable, or a valid symbol + */ +static bool charisok(unsigned char c) { + switch (c) { + case 11: /* block */ + case 16: /* rightarrow */ + case 22: /* circle */ + case 145: /* note */ + case 152: /* bell */ + return true; + break;; + default: + return isprint(c); + } +} + +/**************************************************************************************** + * Show the display (text mode) + */ +static void show_display_buffer(char *ddram) { + char line1[LINELEN+1]; + char *line2; + + memset(line1, 0, LINELEN+1); + strncpy(line1, ddram, LINELEN); + line2 = &(ddram[LINELEN]); + line2[LINELEN] = '\0'; + + /* Convert special LCD chars */ + makeprintable((unsigned char *)line1); + makeprintable((unsigned char *)line2); + + LOG_INFO("\n\t%.40s\n\t%.40s", line1, line2); + + display->text(DISPLAY_TOP_LEFT, DISPLAY_CLEAR, line1); + display->text(DISPLAY_BOTTOM_LEFT, DISPLAY_UPDATE, line2); +} + +/**************************************************************************************** + * Process display data + */ +static void vfdc_handler( u8_t *_data, int bytes_read) { + unsigned short *data = (unsigned short*) _data, *display_data; + char ddram[(LINELEN + 1) * 2]; + int n, addr = 0; /* counter */ + + bytes_read -= 4; + if (bytes_read % 2) bytes_read--; /* even number of bytes */ + // if we use Noritake VFD codes, display data starts at 12 + display_data = &(data[5]); /* display data starts at byte 10 */ + + memset(ddram, ' ', LINELEN * 2); + + for (n = 0; n < (bytes_read/2); n++) { + unsigned short d; /* data element */ + unsigned char t, c; + + d = ntohs(display_data[n]); + t = (d & 0x00ff00) >> 8; /* type of display data */ + c = (d & 0x0000ff); /* character/command */ + switch (t) { + case 0x03: /* character */ + if (!charisok(c)) c = ' '; + if (addr <= LINELEN * 2) { + ddram[addr++] = c; + } + break; + case 0x02: /* command */ + switch (c) { + case 0x06: /* display clear */ + memset(ddram, ' ', LINELEN * 2); + break; + case 0x02: /* cursor home */ + addr = 0; + break; + case 0xc0: /* cursor home2 */ + addr = LINELEN; + break; + } + } + } + + show_display_buffer(ddram); +} + +/**************************************************************************************** + * Process graphic display data + */ +static void grfe_handler( u8_t *data, int len) { + display->v_draw(data + 8); +} + +/**************************************************************************************** + * Brightness + */ +static void grfb_handler(u8_t *data, int len) { + s16_t brightness = htons(*(uint16_t*) (data + 4)); + + LOG_INFO("brightness %hx", brightness); + if (brightness < 0) { + display->on(false); + } else { + display->on(true); + display->brightness(brightness); + } +} + +/**************************************************************************************** + * Scroll set + */ +static void grfs_handler(u8_t *data, int len) { +} + +/**************************************************************************************** + * Scroll go + */ +static void grfg_handler(u8_t *data, int len) { +} + + + + + + + diff --git a/components/squeezelite/embedded.c b/components/squeezelite/embedded.c index a46522c0..6dc3aed0 100644 --- a/components/squeezelite/embedded.c +++ b/components/squeezelite/embedded.c @@ -49,8 +49,10 @@ uint32_t _gettime_ms_(void) { return (uint32_t) (esp_timer_get_time() / 1000); } -extern void cli_controls_init(void); +extern void sb_controls_init(void); +extern void sb_display_init(void); void embedded_init(void) { - cli_controls_init(); + sb_controls_init(); + sb_display_init(); } diff --git a/plugin/SqueezeESP32/Graphics.pm b/plugin/SqueezeESP32/Graphics.pm index 82afe8df..f3faf768 100644 --- a/plugin/SqueezeESP32/Graphics.pm +++ b/plugin/SqueezeESP32/Graphics.pm @@ -61,6 +61,10 @@ sub brightnessMap { return (65535, 10, 50, 100, 200); } +sub hasScrolling { + return 0; +} + =comment sub bytesPerColumn { return 4; diff --git a/plugin/SqueezeESP32/Text.pm b/plugin/SqueezeESP32/Text.pm index 3106a67a..3048c312 100644 --- a/plugin/SqueezeESP32/Text.pm +++ b/plugin/SqueezeESP32/Text.pm @@ -6,8 +6,7 @@ use base qw(Slim::Display::Text); # we don't want the special Noritake codes sub vfdmodel { - return 'squeezeslave''; + return 'squeezeslave'; } - 1; \ No newline at end of file