ソースを参照

refactor display

- part of components
- separation between LMS & driver
- move slimp message to squeezelite
philippe44 5 年 前
コミット
5a9df7b0d5
42 ファイル変更443 行追加316 行削除
  1. 0 13
      components/display/component.mk
  2. 0 119
      components/display/display.c
  3. 1 1
      components/services/buttons.c
  4. 1 1
      components/services/buttons.h
  5. 3 0
      components/services/component.mk
  6. 58 0
      components/services/display.c
  7. 11 11
      components/services/display.h
  8. 70 166
      components/services/driver_SSD1306.c
  9. 0 0
      components/services/tarablessd1306/.gitignore
  10. 0 0
      components/services/tarablessd1306/CMakeLists.txt
  11. 0 0
      components/services/tarablessd1306/Kconfig
  12. 0 0
      components/services/tarablessd1306/LICENSE
  13. 0 0
      components/services/tarablessd1306/README.md
  14. 0 0
      components/services/tarablessd1306/component.mk
  15. 0 0
      components/services/tarablessd1306/fonts/LICENSE-apache
  16. 0 0
      components/services/tarablessd1306/fonts/LICENSE-liberation-mono
  17. 0 0
      components/services/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c
  18. 0 0
      components/services/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c
  19. 0 0
      components/services/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c
  20. 0 0
      components/services/tarablessd1306/fonts/font_droid_sans_mono_13x24.c
  21. 0 0
      components/services/tarablessd1306/fonts/font_droid_sans_mono_16x31.c
  22. 0 0
      components/services/tarablessd1306/fonts/font_droid_sans_mono_7x13.c
  23. 0 0
      components/services/tarablessd1306/fonts/font_liberation_mono_13x21.c
  24. 0 0
      components/services/tarablessd1306/fonts/font_liberation_mono_17x30.c
  25. 0 0
      components/services/tarablessd1306/fonts/font_liberation_mono_9x15.c
  26. 0 0
      components/services/tarablessd1306/fonts/font_tarable7seg_16x32.c
  27. 0 0
      components/services/tarablessd1306/fonts/font_tarable7seg_32x64.c
  28. 0 0
      components/services/tarablessd1306/ifaces/default_if_i2c.c
  29. 0 0
      components/services/tarablessd1306/ifaces/default_if_spi.c
  30. 0 0
      components/services/tarablessd1306/ssd1306.c
  31. 0 0
      components/services/tarablessd1306/ssd1306.h
  32. 0 0
      components/services/tarablessd1306/ssd1306_default_if.h
  33. 0 0
      components/services/tarablessd1306/ssd1306_draw.c
  34. 0 0
      components/services/tarablessd1306/ssd1306_draw.h
  35. 0 0
      components/services/tarablessd1306/ssd1306_err.h
  36. 0 0
      components/services/tarablessd1306/ssd1306_font.c
  37. 0 0
      components/services/tarablessd1306/ssd1306_font.h
  38. 1 1
      components/squeezelite/controls.c
  39. 289 0
      components/squeezelite/display.c
  40. 4 2
      components/squeezelite/embedded.c
  41. 4 0
      plugin/SqueezeESP32/Graphics.pm
  42. 1 2
      plugin/SqueezeESP32/Text.pm

+ 0 - 13
components/display/component.mk

@@ -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
-

+ 0 - 119
components/display/display.c

@@ -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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <string.h>
-#include <ctype.h>
-#include <stdint.h>
-#include <arpa/inet.h>
-#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;
-}
-

+ 1 - 1
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;
 	 }

+ 1 - 1
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);

+ 3 - 0
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

+ 58 - 0
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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#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);
+}

+ 11 - 11
components/display/display.h → 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;

+ 70 - 166
components/display/driver_SSD1306.c → 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 );
-}
-
-/****************************************************************************************
- * 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 );
+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);
 
-	// 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 );
 }
 
 

+ 0 - 0
components/display/tarablessd1306/.gitignore → components/services/tarablessd1306/.gitignore


+ 0 - 0
components/display/tarablessd1306/CMakeLists.txt → components/services/tarablessd1306/CMakeLists.txt


+ 0 - 0
components/display/tarablessd1306/Kconfig → components/services/tarablessd1306/Kconfig


+ 0 - 0
components/display/tarablessd1306/LICENSE → components/services/tarablessd1306/LICENSE


+ 0 - 0
components/display/tarablessd1306/README.md → components/services/tarablessd1306/README.md


+ 0 - 0
components/display/tarablessd1306/component.mk → components/services/tarablessd1306/component.mk


+ 0 - 0
components/display/tarablessd1306/fonts/LICENSE-apache → components/services/tarablessd1306/fonts/LICENSE-apache


+ 0 - 0
components/display/tarablessd1306/fonts/LICENSE-liberation-mono → components/services/tarablessd1306/fonts/LICENSE-liberation-mono


+ 0 - 0
components/display/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c → components/services/tarablessd1306/fonts/font_droid_sans_fallback_11x13.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c → components/services/tarablessd1306/fonts/font_droid_sans_fallback_15x17.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c → components/services/tarablessd1306/fonts/font_droid_sans_fallback_24x28.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_droid_sans_mono_13x24.c → components/services/tarablessd1306/fonts/font_droid_sans_mono_13x24.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_droid_sans_mono_16x31.c → components/services/tarablessd1306/fonts/font_droid_sans_mono_16x31.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_droid_sans_mono_7x13.c → components/services/tarablessd1306/fonts/font_droid_sans_mono_7x13.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_liberation_mono_13x21.c → components/services/tarablessd1306/fonts/font_liberation_mono_13x21.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_liberation_mono_17x30.c → components/services/tarablessd1306/fonts/font_liberation_mono_17x30.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_liberation_mono_9x15.c → components/services/tarablessd1306/fonts/font_liberation_mono_9x15.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_tarable7seg_16x32.c → components/services/tarablessd1306/fonts/font_tarable7seg_16x32.c


+ 0 - 0
components/display/tarablessd1306/fonts/font_tarable7seg_32x64.c → components/services/tarablessd1306/fonts/font_tarable7seg_32x64.c


+ 0 - 0
components/display/tarablessd1306/ifaces/default_if_i2c.c → components/services/tarablessd1306/ifaces/default_if_i2c.c


+ 0 - 0
components/display/tarablessd1306/ifaces/default_if_spi.c → components/services/tarablessd1306/ifaces/default_if_spi.c


+ 0 - 0
components/display/tarablessd1306/ssd1306.c → components/services/tarablessd1306/ssd1306.c


+ 0 - 0
components/display/tarablessd1306/ssd1306.h → components/services/tarablessd1306/ssd1306.h


+ 0 - 0
components/display/tarablessd1306/ssd1306_default_if.h → components/services/tarablessd1306/ssd1306_default_if.h


+ 0 - 0
components/display/tarablessd1306/ssd1306_draw.c → components/services/tarablessd1306/ssd1306_draw.c


+ 0 - 0
components/display/tarablessd1306/ssd1306_draw.h → components/services/tarablessd1306/ssd1306_draw.h


+ 0 - 0
components/display/tarablessd1306/ssd1306_err.h → components/services/tarablessd1306/ssd1306_err.h


+ 0 - 0
components/display/tarablessd1306/ssd1306_font.c → components/services/tarablessd1306/ssd1306_font.c


+ 0 - 0
components/display/tarablessd1306/ssd1306_font.h → components/services/tarablessd1306/ssd1306_font.h


+ 1 - 1
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);

+ 289 - 0
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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <ctype.h>
+#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) {
+}	
+
+
+
+
+
+
+

+ 4 - 2
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();
 }

+ 4 - 0
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;

+ 1 - 2
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;