From 87bb96dfbef93d80d0f682cc98fa02ef80f12e0e Mon Sep 17 00:00:00 2001 From: devsaurus Date: Sat, 18 Nov 2017 21:29:57 +0100 Subject: [PATCH] port u8g2 module from esp32 platform --- Makefile | 12 +- app/Makefile | 2 + app/include/u8g2_displays.h | 14 + app/include/u8g2_fonts.h | 12 + app/include/user_modules.h | 1 + app/modules/Makefile | 1 + app/modules/u8g2.c | 805 ++++++++++++++++++++++ app/platform/Makefile | 1 + app/platform/u8x8_nodemcu_hal.c | 283 ++++++++ app/platform/u8x8_nodemcu_hal.h | 26 + app/u8g2lib/Makefile | 50 ++ app/u8g2lib/u8x8_d_fbrle.c | 185 +++++ lua_examples/u8g2/graphics_test.lua | 263 +++++++ lua_examples/u8glib/u8g_bitmaps.lua | 115 ---- lua_examples/u8glib/u8g_drawloop.lua | 73 -- lua_examples/u8glib/u8g_graphics_test.lua | 177 ----- lua_examples/u8glib/u8g_rook.bm | Bin 8 -> 0 bytes lua_examples/u8glib/u8g_rotation.lua | 97 --- lua_examples/u8glib/u8glib_logo.xbm | Bin 120 -> 0 bytes 19 files changed, 1649 insertions(+), 468 deletions(-) create mode 100644 app/include/u8g2_displays.h create mode 100644 app/include/u8g2_fonts.h create mode 100644 app/modules/u8g2.c create mode 100644 app/platform/u8x8_nodemcu_hal.c create mode 100644 app/platform/u8x8_nodemcu_hal.h create mode 100644 app/u8g2lib/Makefile create mode 100644 app/u8g2lib/u8x8_d_fbrle.c create mode 100644 lua_examples/u8g2/graphics_test.lua delete mode 100644 lua_examples/u8glib/u8g_bitmaps.lua delete mode 100644 lua_examples/u8glib/u8g_drawloop.lua delete mode 100644 lua_examples/u8glib/u8g_graphics_test.lua delete mode 100644 lua_examples/u8glib/u8g_rook.bm delete mode 100644 lua_examples/u8glib/u8g_rotation.lua delete mode 100644 lua_examples/u8glib/u8glib_logo.xbm diff --git a/Makefile b/Makefile index 9709d97a..425780b8 100644 --- a/Makefile +++ b/Makefile @@ -308,11 +308,11 @@ endif $(OBJODIR)/%.o: %.c - @mkdir -p $(OBJODIR); + @mkdir -p $(dir $@); $(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $< $(OBJODIR)/%.d: %.c - @mkdir -p $(OBJODIR); + @mkdir -p $(dir $@); @echo DEPEND: $(CC) -M $(CFLAGS) $< @set -e; rm -f $@; \ $(CC) -M $(CFLAGS) $< > $@.$$$$; \ @@ -331,22 +331,22 @@ $(OBJODIR)/%.d: %.cpp rm -f $@.$$$$ $(OBJODIR)/%.o: %.s - @mkdir -p $(OBJODIR); + @mkdir -p $(dir $@); $(CC) $(CFLAGS) -o $@ -c $< $(OBJODIR)/%.d: %.s - @mkdir -p $(OBJODIR); \ + @mkdir -p $(dir $@); \ set -e; rm -f $@; \ $(CC) -M $(CFLAGS) $< > $@.$$$$; \ sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ $(OBJODIR)/%.o: %.S - @mkdir -p $(OBJODIR); + @mkdir -p $(dir $@); $(CC) $(CFLAGS) -D__ASSEMBLER__ -o $@ -c $< $(OBJODIR)/%.d: %.S - @mkdir -p $(OBJODIR); \ + @mkdir -p $(dir $@); \ set -e; rm -f $@; \ $(CC) -M $(CFLAGS) $< > $@.$$$$; \ sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \ diff --git a/app/Makefile b/app/Makefile index 711cf7a2..9ba4c244 100644 --- a/app/Makefile +++ b/app/Makefile @@ -38,6 +38,7 @@ SUBDIRS= \ lua \ lwip \ task \ + u8g2lib \ smart \ modules \ spiffs \ @@ -68,6 +69,7 @@ COMPONENTS_eagle.app.v6 = \ libc/liblibc.a \ lua/liblua.a \ lwip/liblwip.a \ + u8g2lib/u8g2lib.a \ smart/smart.a \ spiffs/spiffs.a \ fatfs/libfatfs.a \ diff --git a/app/include/u8g2_displays.h b/app/include/u8g2_displays.h new file mode 100644 index 00000000..915f0eed --- /dev/null +++ b/app/include/u8g2_displays.h @@ -0,0 +1,14 @@ + +#ifndef _U8G2_DISPLAYS_H +#define _U8G2_DISPLAYS_H + +#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) + +#define U8G2_DISPLAY_TABLE_I2C \ + U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_i2c_128x64_noname_f, ssd1306_i2c_128x64_noname) \ + +#define U8G2_DISPLAY_TABLE_SPI \ + U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_ssd1306_128x64_noname_f, ssd1306_128x64_noname) \ + + +#endif /* _U8G2_DISPLAYS_H */ diff --git a/app/include/u8g2_fonts.h b/app/include/u8g2_fonts.h new file mode 100644 index 00000000..b72e88ea --- /dev/null +++ b/app/include/u8g2_fonts.h @@ -0,0 +1,12 @@ + +#ifndef _U8G2_FONTS_H +#define _U8G2_FONTS_H + +#define U8G2_FONT_TABLE_ENTRY(font) + +#define U8G2_FONT_TABLE \ + U8G2_FONT_TABLE_ENTRY(font_6x10_tf) \ + U8G2_FONT_TABLE_ENTRY(font_unifont_t_symbols) \ + + +#endif /* _U8G2_FONTS_H */ diff --git a/app/include/user_modules.h b/app/include/user_modules.h index 8f8c0327..009accd9 100644 --- a/app/include/user_modules.h +++ b/app/include/user_modules.h @@ -65,6 +65,7 @@ #define LUA_USE_MODULES_TMR //#define LUA_USE_MODULES_TSL2561 #define LUA_USE_MODULES_UART +//#define LUA_USE_MODULES_U8G2 //#define LUA_USE_MODULES_UCG //#define LUA_USE_MODULES_WEBSOCKET #define LUA_USE_MODULES_WIFI diff --git a/app/modules/Makefile b/app/modules/Makefile index 37a5c1d8..cf80b63c 100644 --- a/app/modules/Makefile +++ b/app/modules/Makefile @@ -43,6 +43,7 @@ INCLUDES += -I ./ INCLUDES += -I ../libc INCLUDES += -I ../coap INCLUDES += -I ../mqtt +INCLUDES += -I ../u8g2lib/u8g2/src/clib INCLUDES += -I ../ucglib INCLUDES += -I ../lua INCLUDES += -I ../pcm diff --git a/app/modules/u8g2.c b/app/modules/u8g2.c new file mode 100644 index 00000000..3d7c5e09 --- /dev/null +++ b/app/modules/u8g2.c @@ -0,0 +1,805 @@ +// Module for binding the u8g2 library +// Note: This file is intended to be shared between esp8266 and esp32 platform + +#include "module.h" +#include "lauxlib.h" + +#define U8X8_USE_PINS +#include "u8g2.h" +#include "u8x8_nodemcu_hal.h" + +#include "u8g2_displays.h" +#include "u8g2_fonts.h" + +#ifdef ESP_PLATFORM +#include "spi_common.h" + +#include "sdkconfig.h" +#endif + +#ifndef CONFIG_LUA_MODULE_U8G2 +// ignore unused functions if u8g2 module will be skipped anyhow +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + + +typedef struct { + int font_ref; + int host_ref; + u8g2_nodemcu_t u8g2; +} u8g2_ud_t; + +#define GET_U8G2() \ + u8g2_ud_t *ud = (u8g2_ud_t *)luaL_checkudata( L, 1, "u8g2.display" ); \ + u8g2_t *u8g2 = (u8g2_t *)(&(ud->u8g2)); + +static int lu8g2_clearBuffer( lua_State *L ) +{ + GET_U8G2(); + + u8g2_ClearBuffer( u8g2 ); + + return 0; +} + +static int lu8g2_drawBox( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int w = luaL_checkint( L, ++stack ); + int h = luaL_checkint( L, ++stack ); + + u8g2_DrawBox( u8g2, x, y, w, h ); + + return 0; +} + +static int lu8g2_drawCircle( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x0 = luaL_checkint( L, ++stack ); + int y0 = luaL_checkint( L, ++stack ); + int rad = luaL_checkint( L, ++stack ); + int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL ); + + u8g2_DrawCircle( u8g2, x0, y0, rad, opt ); + + return 0; +} + +static int lu8g2_drawDisc( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x0 = luaL_checkint( L, ++stack ); + int y0 = luaL_checkint( L, ++stack ); + int rad = luaL_checkint( L, ++stack ); + int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL ); + + u8g2_DrawDisc( u8g2, x0, y0, rad, opt ); + + return 0; +} + +static int lu8g2_drawEllipse( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x0 = luaL_checkint( L, ++stack ); + int y0 = luaL_checkint( L, ++stack ); + int rx = luaL_checkint( L, ++stack ); + int ry = luaL_checkint( L, ++stack ); + int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL ); + + u8g2_DrawEllipse( u8g2, x0, y0, rx, ry, opt ); + + return 0; +} + +static int lu8g2_drawFilledEllipse( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x0 = luaL_checkint( L, ++stack ); + int y0 = luaL_checkint( L, ++stack ); + int rx = luaL_checkint( L, ++stack ); + int ry = luaL_checkint( L, ++stack ); + int opt = luaL_optint( L, ++stack, U8G2_DRAW_ALL ); + + u8g2_DrawFilledEllipse( u8g2, x0, y0, rx, ry, opt ); + + return 0; +} + +static int lu8g2_drawFrame( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int w = luaL_checkint( L, ++stack ); + int h = luaL_checkint( L, ++stack ); + + u8g2_DrawFrame( u8g2, x, y, w, h ); + + return 0; +} + +static int lu8g2_drawGlyph( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int enc = luaL_checkint( L, ++stack ); + + u8g2_DrawGlyph( u8g2, x, y, enc ); + + return 0; +} + +static int lu8g2_drawHLine( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int w = luaL_checkint( L, ++stack ); + + u8g2_DrawHLine( u8g2, x, y, w ); + + return 0; +} + +static int lu8g2_drawLine( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x0 = luaL_checkint( L, ++stack ); + int y0 = luaL_checkint( L, ++stack ); + int x1 = luaL_checkint( L, ++stack ); + int y1 = luaL_checkint( L, ++stack ); + + u8g2_DrawLine( u8g2, x0, y0, x1, y1 ); + + return 0; +} + +static int lu8g2_drawPixel( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + + u8g2_DrawPixel( u8g2, x, y ); + + return 0; +} + +static int lu8g2_drawRBox( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int w = luaL_checkint( L, ++stack ); + int h = luaL_checkint( L, ++stack ); + int r = luaL_checkint( L, ++stack ); + + u8g2_DrawRBox( u8g2, x, y, w, h, r ); + + return 0; +} + +static int lu8g2_drawRFrame( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int w = luaL_checkint( L, ++stack ); + int h = luaL_checkint( L, ++stack ); + int r = luaL_checkint( L, ++stack ); + + u8g2_DrawRFrame( u8g2, x, y, w, h, r ); + + return 0; +} + +static int lu8g2_drawStr( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + const char *str = luaL_checkstring( L, ++stack ); + + u8g2_DrawStr( u8g2, x, y, str ); + + return 0; +} + +static int lu8g2_drawTriangle( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x0 = luaL_checkint( L, ++stack ); + int y0 = luaL_checkint( L, ++stack ); + int x1 = luaL_checkint( L, ++stack ); + int y1 = luaL_checkint( L, ++stack ); + int x2 = luaL_checkint( L, ++stack ); + int y2 = luaL_checkint( L, ++stack ); + + u8g2_DrawTriangle( u8g2, x0, y0, x1, y1, x2, y2 ); + + return 0; +} + +static int lu8g2_drawUTF8( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + const char *str = luaL_checkstring( L, ++stack ); + + u8g2_DrawUTF8( u8g2, x, y, str ); + + return 0; +} + +static int lu8g2_drawVLine( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int h = luaL_checkint( L, ++stack ); + + u8g2_DrawVLine( u8g2, x, y, h ); + + return 0; +} + +static int lu8g2_drawXBM( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int x = luaL_checkint( L, ++stack ); + int y = luaL_checkint( L, ++stack ); + int w = luaL_checkint( L, ++stack ); + int h = luaL_checkint( L, ++stack ); + size_t len; + const char *bitmap = luaL_checklstring( L, ++stack, &len ); + + u8g2_DrawXBM( u8g2, x, y, w, h, (uint8_t *)bitmap ); + + return 0; +} + +static int lu8g2_getAscent( lua_State *L ) +{ + GET_U8G2(); + + lua_pushinteger( L, u8g2_GetAscent( u8g2 ) ); + return 1; +} + +static int lu8g2_getDescent( lua_State *L ) +{ + GET_U8G2(); + + lua_pushinteger( L, u8g2_GetDescent( u8g2 ) ); + return 1; +} + +static int lu8g2_getStrWidth( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + const char *s = luaL_checkstring( L, ++stack ); + + lua_pushinteger( L, u8g2_GetStrWidth( u8g2, s ) ); + return 1; +} + +static int lu8g2_getUTF8Width( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + const char *s = luaL_checkstring( L, ++stack ); + + lua_pushinteger( L, u8g2_GetUTF8Width( u8g2, s ) ); + return 1; +} + +static int lu8g2_sendBuffer( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SendBuffer( u8g2 ); + + return 0; +} + +static int lu8g2_setBitmapMode( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int is_transparent = luaL_checkint( L, ++stack ); + + u8g2_SetBitmapMode( u8g2, is_transparent ); + + return 0; +} + +static int lu8g2_setContrast( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int value = luaL_checkint( L, ++stack ); + + u8g2_SetContrast( u8g2, value ); + + return 0; +} + +static int lu8g2_setDisplayRotation( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + const u8g2_cb_t *u8g2_cb = (u8g2_cb_t *)lua_touserdata( L, ++stack ); + + u8g2_SetDisplayRotation( u8g2, u8g2_cb ); + + return 0; +} + +static int lu8g2_setDrawColor( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int col = luaL_checkint( L, ++stack ); + + u8g2_SetDrawColor( u8g2, col ); + + return 0; +} + +static int lu8g2_setFlipMode( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int is_enable = luaL_checkint( L, ++stack ); + + u8g2_SetFlipMode( u8g2, is_enable ); + + return 0; +} + +static int lu8g2_setFont( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + const uint8_t *font = NULL; + + luaL_unref( L, LUA_REGISTRYINDEX, ud->font_ref ); + ud->font_ref = LUA_NOREF; + + if (lua_islightuserdata( L, ++stack )) { + font = (const uint8_t *)lua_touserdata( L, stack ); + + } else if (lua_isstring( L, stack )) { + // ref the font string to safe it in case the string variable gets gc'ed + lua_pushvalue( L, stack ); + ud->font_ref = luaL_ref( L, LUA_REGISTRYINDEX ); + + size_t len; + font = (const uint8_t *)luaL_checklstring( L, stack, &len ); + + } + luaL_argcheck( L, font != NULL, stack, "invalid font" ); + + u8g2_SetFont( u8g2, font ); + + return 0; +} + +static int lu8g2_setFontDirection( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int dir = luaL_checkint( L, ++stack ); + + u8g2_SetFontDirection( u8g2, dir ); + + return 0; +} + +static int lu8g2_setFontMode( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int is_transparent = luaL_checkint( L, ++stack ); + + u8g2_SetFontMode( u8g2, is_transparent ); + + return 0; +} + +static int lu8g2_setFontPosBaseline( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontPosBaseline( u8g2 ); + + return 0; +} + +static int lu8g2_setFontPosBottom( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontPosBottom( u8g2 ); + + return 0; +} + +static int lu8g2_setFontPosTop( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontPosTop( u8g2 ); + + return 0; +} + +static int lu8g2_setFontPosCenter( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontPosCenter( u8g2 ); + + return 0; +} + +static int lu8g2_setFontRefHeightAll( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontRefHeightAll( u8g2 ); + + return 0; +} + +static int lu8g2_setFontRefHeightExtendedText( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontRefHeightExtendedText( u8g2 ); + + return 0; +} + +static int lu8g2_setFontRefHeightText( lua_State *L ) +{ + GET_U8G2(); + + u8g2_SetFontRefHeightText( u8g2 ); + + return 0; +} + +static int lu8g2_setPowerSave( lua_State *L ) +{ + GET_U8G2(); + int stack = 1; + + int is_enable = luaL_checkint( L, ++stack ); + + u8g2_SetPowerSave( u8g2, is_enable ); + + return 0; +} + + +static const LUA_REG_TYPE lu8g2_display_map[] = { + { LSTRKEY( "clearBuffer" ), LFUNCVAL( lu8g2_clearBuffer ) }, + { LSTRKEY( "drawBox" ), LFUNCVAL( lu8g2_drawBox ) }, + { LSTRKEY( "drawCircle" ), LFUNCVAL( lu8g2_drawCircle ) }, + { LSTRKEY( "drawDisc" ), LFUNCVAL( lu8g2_drawDisc ) }, + { LSTRKEY( "drawEllipse" ), LFUNCVAL( lu8g2_drawEllipse ) }, + { LSTRKEY( "drawFilledEllipse" ), LFUNCVAL( lu8g2_drawFilledEllipse ) }, + { LSTRKEY( "drawFrame" ), LFUNCVAL( lu8g2_drawFrame ) }, + { LSTRKEY( "drawGlyph" ), LFUNCVAL( lu8g2_drawGlyph ) }, + { LSTRKEY( "drawHLine" ), LFUNCVAL( lu8g2_drawHLine ) }, + { LSTRKEY( "drawLine" ), LFUNCVAL( lu8g2_drawLine ) }, + { LSTRKEY( "drawPixel" ), LFUNCVAL( lu8g2_drawPixel ) }, + { LSTRKEY( "drawRBox" ), LFUNCVAL( lu8g2_drawRBox ) }, + { LSTRKEY( "drawRFrame" ), LFUNCVAL( lu8g2_drawRFrame ) }, + { LSTRKEY( "drawStr" ), LFUNCVAL( lu8g2_drawStr ) }, + { LSTRKEY( "drawTriangle" ), LFUNCVAL( lu8g2_drawTriangle ) }, + { LSTRKEY( "drawUTF8" ), LFUNCVAL( lu8g2_drawUTF8 ) }, + { LSTRKEY( "drawVLine" ), LFUNCVAL( lu8g2_drawVLine ) }, + { LSTRKEY( "drawXBM" ), LFUNCVAL( lu8g2_drawXBM ) }, + { LSTRKEY( "getAscent" ), LFUNCVAL( lu8g2_getAscent ) }, + { LSTRKEY( "getDescent" ), LFUNCVAL( lu8g2_getDescent ) }, + { LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g2_getStrWidth ) }, + { LSTRKEY( "getUTF8Width" ), LFUNCVAL( lu8g2_getUTF8Width ) }, + { LSTRKEY( "sendBuffer" ), LFUNCVAL( lu8g2_sendBuffer ) }, + { LSTRKEY( "setBitmapMode" ), LFUNCVAL( lu8g2_setBitmapMode ) }, + { LSTRKEY( "setContrast" ), LFUNCVAL( lu8g2_setContrast ) }, + { LSTRKEY( "setDisplayRotation" ), LFUNCVAL( lu8g2_setDisplayRotation ) }, + { LSTRKEY( "setDrawColor" ), LFUNCVAL( lu8g2_setDrawColor ) }, + { LSTRKEY( "setFlipMode" ), LFUNCVAL( lu8g2_setFlipMode ) }, + { LSTRKEY( "setFont" ), LFUNCVAL( lu8g2_setFont ) }, + { LSTRKEY( "setFontDirection" ), LFUNCVAL( lu8g2_setFontDirection ) }, + { LSTRKEY( "setFontMode" ), LFUNCVAL( lu8g2_setFontMode ) }, + { LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lu8g2_setFontPosBaseline ) }, + { LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lu8g2_setFontPosBottom ) }, + { LSTRKEY( "setFontPosTop" ), LFUNCVAL( lu8g2_setFontPosTop ) }, + { LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lu8g2_setFontPosCenter ) }, + { LSTRKEY( "setFontRefHeightAll" ), LFUNCVAL( lu8g2_setFontRefHeightAll ) }, + { LSTRKEY( "setFontRefHeightExtendedText" ), LFUNCVAL( lu8g2_setFontRefHeightExtendedText ) }, + { LSTRKEY( "setFontRefHeightText" ), LFUNCVAL( lu8g2_setFontRefHeightText ) }, + { LSTRKEY( "setPowerSave" ), LFUNCVAL( lu8g2_setPowerSave ) }, + //{ LSTRKEY( "__gc" ), LFUNCVAL( lu8g2_display_free ) }, + { LSTRKEY( "__index" ), LROVAL( lu8g2_display_map ) }, + {LNILKEY, LNILVAL} +}; + + +uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); + +typedef void (*display_setup_fn_t)(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb); + +// *************************************************************************** +// Device constructors +// +// I2C based devices will use this function template to implement the Lua binding. +// +static int ldisplay_i2c( lua_State *L, display_setup_fn_t setup_fn ) +{ + int stack = 0; + + int id = -1; + int i2c_addr = -1; + int rfb_cb_ref = LUA_NOREF; + + if (lua_type( L, ++stack) == LUA_TNUMBER) { + /* hardware display connected */ + id = luaL_checkint( L, stack ); + i2c_addr = luaL_checkint( L, ++stack ); + luaL_argcheck( L, i2c_addr >= 0 && i2c_addr <= 0x7f, stack, "invalid i2c address" ); + } else + stack--; + if (lua_isfunction( L, ++stack )) { + lua_pushvalue( L, stack ); + rfb_cb_ref = luaL_ref( L, LUA_REGISTRYINDEX ); + } + if (id < 0 && rfb_cb_ref == LUA_NOREF) + return luaL_error( L, "wrong args" ); + + u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) ); + u8g2_nodemcu_t *ext_u8g2 = &(ud->u8g2); + ud->font_ref = LUA_NOREF; + ud->host_ref = LUA_NOREF; + /* the i2c driver id is forwarded in the hal member */ + ext_u8g2->hal = id >= 0 ? (void *)id : NULL; + + u8g2_t *u8g2 = (u8g2_t *)ext_u8g2; + u8x8_t *u8x8 = (u8x8_t *)u8g2; + + setup_fn( u8g2, U8G2_R0, u8x8_byte_nodemcu_i2c, u8x8_gpio_and_delay_nodemcu ); + + /* prepare overlay data */ + if (rfb_cb_ref != LUA_NOREF) { + ext_u8g2->overlay.template_display_cb = u8x8->display_cb; + ext_u8g2->overlay.hardware_display_cb = NULL; + ext_u8g2->overlay.rfb_cb_ref = LUA_NOREF; + u8x8->display_cb = u8x8_d_overlay; + } + if (id >= 0) { + /* hardware device specific initialization */ + u8x8_SetI2CAddress( u8x8, i2c_addr ); + ext_u8g2->overlay.hardware_display_cb = ext_u8g2->overlay.template_display_cb; + } + + u8g2_InitDisplay( (u8g2_t *)u8g2 ); + u8g2_ClearDisplay( (u8g2_t *)u8g2 ); + u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 ); + + if (rfb_cb_ref != LUA_NOREF) { + /* finally enable rfb display driver */ + ext_u8g2->overlay.rfb_cb_ref = rfb_cb_ref; + } + + /* set its metatable */ + luaL_getmetatable(L, "u8g2.display"); + lua_setmetatable(L, -2); + + return 1; +} +// +// SPI based devices will use this function template to implement the Lua binding. +// +static int ldisplay_spi( lua_State *L, display_setup_fn_t setup_fn ) +{ + int stack = 0; + +#ifndef ESP_PLATFORM + typedef struct { + int host; + } lspi_host_t; + lspi_host_t host_elem; + lspi_host_t *host = &host_elem; +#else + lspi_host_t *host = NULL; +#endif + int host_ref = LUA_NOREF; + int cs = -1; + int dc = -1; + int res = -1; + int rfb_cb_ref = LUA_NOREF; + int get_spi_pins; + + + if (lua_type( L, ++stack ) == LUA_TUSERDATA) { + host = (lspi_host_t *)luaL_checkudata( L, stack, "spi.master" ); + /* reference host object to avoid automatic gc */ + lua_pushvalue( L, stack ); + host_ref = luaL_ref( L, LUA_REGISTRYINDEX ); + get_spi_pins = TRUE; + } else if (lua_type( L, stack ) == LUA_TNUMBER) { + host->host = luaL_checkint( L, stack ); + get_spi_pins = TRUE; + } else { + get_spi_pins = FALSE; + stack--; + } + + if (get_spi_pins) { + cs = luaL_checkint( L, ++stack ); + dc = luaL_checkint( L, ++stack ); + res = luaL_optint( L, ++stack, -1 ); + } + + if (lua_isfunction( L, ++stack )) { + lua_pushvalue( L, stack ); + rfb_cb_ref = luaL_ref( L, LUA_REGISTRYINDEX ); + } + if (!host && rfb_cb_ref == LUA_NOREF) + return luaL_error( L, "wrong args" ); + + u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) ); + u8g2_nodemcu_t *ext_u8g2 = &(ud->u8g2); + ud->font_ref = LUA_NOREF; + ud->host_ref = host_ref; + /* the spi host id is forwarded in the hal member */ + ext_u8g2->hal = host ? (void *)(host->host) : NULL; + + u8g2_t *u8g2 = (u8g2_t *)ext_u8g2; + u8x8_t *u8x8 = (u8x8_t *)u8g2; + + setup_fn( u8g2, U8G2_R0, u8x8_byte_nodemcu_spi, u8x8_gpio_and_delay_nodemcu ); + + /* prepare overlay data */ + if (rfb_cb_ref != LUA_NOREF) { + ext_u8g2->overlay.template_display_cb = u8x8->display_cb; + ext_u8g2->overlay.hardware_display_cb = NULL; + ext_u8g2->overlay.rfb_cb_ref = LUA_NOREF; + u8x8->display_cb = u8x8_d_overlay; + } + if (host) { + /* hardware specific device initialization */ + u8x8_SetPin( u8x8, U8X8_PIN_CS, cs ); + u8x8_SetPin( u8x8, U8X8_PIN_DC, dc ); + if (res >= 0) + u8x8_SetPin( u8x8, U8X8_PIN_RESET, res ); + ext_u8g2->overlay.hardware_display_cb = ext_u8g2->overlay.template_display_cb; + } + + u8g2_InitDisplay( (u8g2_t *)u8g2 ); + u8g2_ClearDisplay( (u8g2_t *)u8g2 ); + u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 ); + + if (rfb_cb_ref != LUA_NOREF) { + /* finally enable rfb display driver */ + ext_u8g2->overlay.rfb_cb_ref = rfb_cb_ref; + } + + /* set its metatable */ + luaL_getmetatable(L, "u8g2.display"); + lua_setmetatable(L, -2); + + return 1; +} +// +// +#undef U8G2_DISPLAY_TABLE_ENTRY +#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \ + static int l ## binding( lua_State *L ) \ + { \ + return ldisplay_i2c( L, function ); \ + } +// +// Unroll the display table and insert binding functions for I2C based displays. +U8G2_DISPLAY_TABLE_I2C +// +// +#undef U8G2_DISPLAY_TABLE_ENTRY +#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \ + static int l ## binding( lua_State *L ) \ + { \ + return ldisplay_spi( L, function ); \ + } +// +// Unroll the display table and insert binding functions for SPI based displays. +U8G2_DISPLAY_TABLE_SPI +// + + +#undef U8G2_FONT_TABLE_ENTRY +#undef U8G2_DISPLAY_TABLE_ENTRY +#define U8G2_DISPLAY_TABLE_ENTRY(function, binding) \ + { LSTRKEY( #binding ), LFUNCVAL( l ## binding ) }, + +static const LUA_REG_TYPE lu8g2_map[] = { + U8G2_DISPLAY_TABLE_I2C + U8G2_DISPLAY_TABLE_SPI + // + // Register fonts +#define U8G2_FONT_TABLE_ENTRY(font) \ + { LSTRKEY( #font ), LUDATA( (void *)(u8g2_ ## font) ) }, + U8G2_FONT_TABLE + // + { LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( U8G2_DRAW_UPPER_RIGHT ) }, + { LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( U8G2_DRAW_UPPER_LEFT ) }, + { LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( U8G2_DRAW_LOWER_RIGHT ) }, + { LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( U8G2_DRAW_LOWER_LEFT ) }, + { LSTRKEY( "DRAW_ALL" ), LNUMVAL( U8G2_DRAW_ALL ) }, + { LSTRKEY( "R0" ), LUDATA( (void *)U8G2_R0 ) }, + { LSTRKEY( "R1" ), LUDATA( (void *)U8G2_R1 ) }, + { LSTRKEY( "R2" ), LUDATA( (void *)U8G2_R2 ) }, + { LSTRKEY( "R3" ), LUDATA( (void *)U8G2_R3 ) }, + { LSTRKEY( "MIRROR" ), LUDATA( (void *)U8G2_MIRROR ) }, + {LNILKEY, LNILVAL} +}; + +int luaopen_u8g2( lua_State *L ) { + luaL_rometatable(L, "u8g2.display", (void *)lu8g2_display_map); + return 0; +} + +NODEMCU_MODULE(U8G2, "u8g2", lu8g2_map, luaopen_u8g2); diff --git a/app/platform/Makefile b/app/platform/Makefile index 18efcabe..00485dcb 100644 --- a/app/platform/Makefile +++ b/app/platform/Makefile @@ -43,6 +43,7 @@ INCLUDES += -I ./ INCLUDES += -I ../spiffs INCLUDES += -I ../libc INCLUDES += -I ../lua +INCLUDES += -I ../u8g2lib/u8g2/src/clib PDIR := ../$(PDIR) sinclude $(PDIR)Makefile diff --git a/app/platform/u8x8_nodemcu_hal.c b/app/platform/u8x8_nodemcu_hal.c new file mode 100644 index 00000000..fee13381 --- /dev/null +++ b/app/platform/u8x8_nodemcu_hal.c @@ -0,0 +1,283 @@ + +#include +#include "c_stdlib.h" + +#include "platform.h" + +#define U8X8_USE_PINS +#include "u8x8_nodemcu_hal.h" + + +uint8_t u8x8_gpio_and_delay_nodemcu(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint32_t temp; + + switch(msg) + { + case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8 + // can be used to setup pins + for (int idx = 0; idx < U8X8_PIN_OUTPUT_CNT; idx++) { + if (u8x8->pins[idx] != U8X8_PIN_NONE) { + // configure pin as output + if (idx == U8X8_PIN_I2C_CLOCK || idx == U8X8_PIN_I2C_DATA) { + platform_gpio_mode( u8x8->pins[idx], PLATFORM_GPIO_OPENDRAIN, PLATFORM_GPIO_PULLUP ); + } else { + platform_gpio_mode( u8x8->pins[idx], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT ); + } + } + } + break; + + case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second + os_delay_us( 1 ); + break; + + case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds + temp = arg_int * 100; + temp /= 1000; + os_delay_us( temp > 0 ? temp : 1 ); + break; + + case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds + os_delay_us( arg_int * 10 ); + break; + + case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second + os_delay_us( arg_int * 1000 ); + break; + + case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz + temp = 5000 / arg_int; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us + temp /= 1000; + os_delay_us( temp > 0 ? temp : 1 ); + break; + + case U8X8_MSG_GPIO_D0: // D0 or SPI clock pin: Output level in arg_int + //case U8X8_MSG_GPIO_SPI_CLOCK: + break; + case U8X8_MSG_GPIO_D1: // D1 or SPI data pin: Output level in arg_int + //case U8X8_MSG_GPIO_SPI_DATA: + break; + case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int + platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int ); + break; + case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int + platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int ); + break; + case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int + if (u8x8_GetPinValue( u8x8, msg ) != U8X8_PIN_NONE) + platform_gpio_write( u8x8_GetPinValue(u8x8, msg), arg_int ); + break; + case U8X8_MSG_GPIO_CS1: // CS1 (chip select) pin: Output level in arg_int + break; + case U8X8_MSG_GPIO_CS2: // CS2 (chip select) pin: Output level in arg_int + break; + + case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin + // arg_int=1: Input dir with pullup high for I2C clock pin + // for SW comm routine + platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int ); + break; + + case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin + // arg_int=1: Input dir with pullup high for I2C data pin + // for SW comm routine + platform_gpio_write( u8x8_GetPinValue( u8x8, msg ), arg_int ); + break; + + case U8X8_MSG_GPIO_MENU_SELECT: + case U8X8_MSG_GPIO_MENU_NEXT: + case U8X8_MSG_GPIO_MENU_PREV: + case U8X8_MSG_GPIO_MENU_HOME: + u8x8_SetGPIOResult( u8x8, /* get menu select pin state */ 0 ); + break; + default: + u8x8_SetGPIOResult( u8x8, 1 ); // default return value + break; + } + return 1; +} + + +// static variables containing info about the i2c link +// TODO: move to user space in u8x8_t once available +typedef struct { + uint8_t id; +} hal_i2c_t; + +uint8_t u8x8_byte_nodemcu_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t *data; + hal_i2c_t *hal = ((u8g2_nodemcu_t *)u8x8)->hal; + + switch(msg) { + case U8X8_MSG_BYTE_SEND: + if (hal->id == 0) { + data = (uint8_t *)arg_ptr; + + while( arg_int > 0 ) { + platform_i2c_send_byte( 0, *data ); + data++; + arg_int--; + } + + } else { + // invalid id + return 0; + } + + break; + + case U8X8_MSG_BYTE_INIT: + { + // the hal member initially contains the i2c id + int id = (int)hal; + if (!(hal = c_malloc( sizeof ( hal_i2c_t ) ))) + return 0; + hal->id = id; + ((u8g2_nodemcu_t *)u8x8)->hal = hal; + } + break; + + case U8X8_MSG_BYTE_SET_DC: + break; + + case U8X8_MSG_BYTE_START_TRANSFER: + if (hal->id == 0) { + platform_i2c_send_start( 0 ); + platform_i2c_send_address( 0, u8x8_GetI2CAddress(u8x8), PLATFORM_I2C_DIRECTION_TRANSMITTER ); + + } else { + // invalid id + return 0; + } + break; + + case U8X8_MSG_BYTE_END_TRANSFER: + if (hal->id == 0) { + platform_i2c_send_stop( 0 ); + + } else { + // invalid id + return 0; + } + break; + + default: + return 0; + } + + return 1; +} + + +// static variables containing info about the spi link +// TODO: move to user space in u8x8_t once available +typedef struct { + uint8_t host; + //spi_device_handle_t device; + uint8_t last_dc; + struct { + uint8_t *data; + size_t size, used; + } buffer; +} hal_spi_t; + +static void flush_buffer_spi( hal_spi_t *hal ) +{ + if (hal->buffer.used > 0) { + platform_spi_blkwrite( hal->host, hal->buffer.used, hal->buffer.data ); + + hal->buffer.used = 0; + } +} + +uint8_t u8x8_byte_nodemcu_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + hal_spi_t *hal = ((u8g2_nodemcu_t *)u8x8)->hal; + + switch(msg) { + case U8X8_MSG_BYTE_INIT: + { + /* disable chipselect */ + u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level ); + + // the hal member initially contains the spi host id + int host = (int)hal; + if (!(hal = c_malloc( sizeof ( hal_spi_t ) ))) + return 0; + hal->host = host; + ((u8g2_nodemcu_t *)u8x8)->hal = hal; + + hal->last_dc = 0; + } + break; + + case U8X8_MSG_BYTE_SET_DC: + if (hal->last_dc != arg_int) + flush_buffer_spi( hal ); + + u8x8_gpio_SetDC( u8x8, arg_int ); + hal->last_dc = arg_int; + break; + + case U8X8_MSG_BYTE_START_TRANSFER: + hal->buffer.size = 256; + if (!(hal->buffer.data = (uint8_t *)c_malloc( hal->buffer.size ))) + return 0; + hal->buffer.used = 0; + + u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_enable_level ); + break; + + case U8X8_MSG_BYTE_SEND: + if (!hal->buffer.data) + return 0; + + while (hal->buffer.size - hal->buffer.used < arg_int) { + hal->buffer.size *= 2; + uint8_t *tmp; + if (!(tmp = (uint8_t *)c_malloc( hal->buffer.size ))) { + c_free( hal->buffer.data ); + hal->buffer.data = NULL; + return 0; + } + os_memcpy( tmp, hal->buffer.data, hal->buffer.used ); + c_free( hal->buffer.data ); + hal->buffer.data = tmp; + } + os_memcpy( hal->buffer.data + hal->buffer.used, arg_ptr, arg_int ); + hal->buffer.used += arg_int; + break; + + case U8X8_MSG_BYTE_END_TRANSFER: + if (!hal->buffer.data) + return 0; + + flush_buffer_spi( hal ); + + u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level ); + + c_free( hal->buffer.data ); + break; + + default: + return 0; + } + + return 1; +} diff --git a/app/platform/u8x8_nodemcu_hal.h b/app/platform/u8x8_nodemcu_hal.h new file mode 100644 index 00000000..22a17402 --- /dev/null +++ b/app/platform/u8x8_nodemcu_hal.h @@ -0,0 +1,26 @@ + +#ifndef _U8X8_NODEMCU_HAL_H +#define _U8X8_NODEMCU_HAL_H + +#include "u8g2.h" + + +// extend standard u8g2_t struct with info that's needed in the communication callbacks +typedef struct { + u8g2_t u8g2; + void *hal; + + // elements for the overlay display driver + struct { + u8x8_msg_cb hardware_display_cb, template_display_cb; + int rfb_cb_ref; + uint8_t fb_update_ongoing; + } overlay; +} u8g2_nodemcu_t; + + +uint8_t u8x8_gpio_and_delay_nodemcu(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); +uint8_t u8x8_byte_nodemcu_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); +uint8_t u8x8_byte_nodemcu_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); + +#endif /* _U8X8_NODEMCU_HAL_H */ diff --git a/app/u8g2lib/Makefile b/app/u8g2lib/Makefile new file mode 100644 index 00000000..3916564f --- /dev/null +++ b/app/u8g2lib/Makefile @@ -0,0 +1,50 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = u8g2lib.a +endif + +STD_CFLAGS=-std=gnu11 -Wimplicit + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +DEFINES += -DU8X8_USE_PINS + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +CSRCS := $(wildcard u8g2/src/clib/*.c *.c) + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I u8g2/src/clib +INCLUDES += -I ../libc +INCLUDES += -I ../lua +INCLUDES += -I ../platform +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/u8g2lib/u8x8_d_fbrle.c b/app/u8g2lib/u8x8_d_fbrle.c new file mode 100644 index 00000000..b6abf663 --- /dev/null +++ b/app/u8g2lib/u8x8_d_fbrle.c @@ -0,0 +1,185 @@ + +// Note: This file is intended to be shared between esp8266 and esp32 platform + +#include "u8x8.h" +#include "lauxlib.h" + +#include "u8x8_nodemcu_hal.h" + +#include +#include + + +static const u8x8_display_info_t u8x8_fbrle_display_info = +{ + /* chip_enable_level = */ 0, + /* chip_disable_level = */ 1, + + /* post_chip_enable_wait_ns = */ 0, + /* pre_chip_disable_wait_ns = */ 0, + /* reset_pulse_width_ms = */ 0, + /* post_reset_wait_ms = */ 0, + /* sda_setup_time_ns = */ 0, + /* sck_pulse_width_ns = */ 0, + /* sck_clock_hz = */ 0, + /* spi_mode = */ 0, + /* i2c_bus_clock_100kHz = */ 4, + /* data_setup_time_ns = */ 0, + /* write_pulse_width_ns = */ 0, + /* tile_width = */ 16, + /* tile_hight = */ 8, + /* default_x_offset = */ 0, + /* flipmode_x_offset = */ 0, + /* pixel_width = */ 128, + /* pixel_height = */ 64 +}; + +static int bit_at( uint8_t *buf, int line, int x ) +{ + return buf[x] & (1 << line) ? 1 : 0; +} + +struct fbrle_item +{ + uint8_t start_x; + uint8_t len; +}; + +struct fbrle_line +{ + uint8_t num_valid; + struct fbrle_item items[0]; +}; + +static uint8_t u8x8_d_fbrle(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + u8g2_nodemcu_t *ext_u8g2 = (u8g2_nodemcu_t *)u8x8; + + switch(msg) + { + case U8X8_MSG_DISPLAY_SETUP_MEMORY: + // forward to template display driver + return ext_u8g2->overlay.template_display_cb(u8x8, msg, arg_int, arg_ptr); + + case U8X8_MSG_DISPLAY_INIT: + //u8x8_d_helper_display_init(u8x8); + ext_u8g2->overlay.fb_update_ongoing = 0; + break; + + case U8X8_MSG_DISPLAY_SET_POWER_SAVE: + case U8X8_MSG_DISPLAY_SET_FLIP_MODE: + break; + +#ifdef U8X8_WITH_SET_CONTRAST + case U8X8_MSG_DISPLAY_SET_CONTRAST: + break; +#endif + + case U8X8_MSG_DISPLAY_REFRESH: + ext_u8g2->overlay.fb_update_ongoing = 0; + break; + + case U8X8_MSG_DISPLAY_DRAW_TILE: + if (ext_u8g2->overlay.fb_update_ongoing == 0) { + // tell rfb callback that a new framebuffer starts + if (ext_u8g2->overlay.rfb_cb_ref != LUA_NOREF) { + // fire callback with nil argument + lua_State *L = lua_getstate(); + lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref ); + lua_pushnil( L ); + lua_call( L, 1, 0 ); + } + // and note ongoing framebuffer update + ext_u8g2->overlay.fb_update_ongoing = 1; + } + + { + // TODO: transport tile_y, needs structural change! + uint8_t tile_x = ((u8x8_tile_t *)arg_ptr)->x_pos; + tile_x *= 8; + tile_x += u8x8->x_offset; + uint8_t tile_w = ((u8x8_tile_t *)arg_ptr)->cnt * 8; + + size_t fbrle_line_size = sizeof( struct fbrle_line ) + sizeof( struct fbrle_item ) * (tile_w/2); + int num_lines = 8; /*arg_val / (xwidth/8);*/ + uint8_t *buf = ((u8x8_tile_t *)arg_ptr)->tile_ptr; + + struct fbrle_line *fbrle_line; + if (!(fbrle_line = (struct fbrle_line *)malloc( fbrle_line_size ))) { + break; + } + + for (int line = 0; line < num_lines; line++) { + int start_run = -1; + fbrle_line->num_valid = 0; + + for (int x = tile_x; x < tile_x+tile_w; x++) { + if (bit_at( buf, line, x ) == 0) { + if (start_run >= 0) { + // inside run, end it and enter result + fbrle_line->items[fbrle_line->num_valid].start_x = start_run; + fbrle_line->items[fbrle_line->num_valid++].len = x - start_run; + //NODE_ERR( " line: %d x: %d len: %d\n", line, start_run, x - start_run ); + start_run = -1; + } + } else { + if (start_run < 0) { + // outside run, start it + start_run = x; + } + } + + if (fbrle_line->num_valid >= tile_w/2) break; + } + + // active run? + if (start_run >= 0 && fbrle_line->num_valid < tile_w/2) { + fbrle_line->items[fbrle_line->num_valid].start_x = start_run; + fbrle_line->items[fbrle_line->num_valid++].len = tile_w - start_run; + } + + // line done, trigger callback + if (ext_u8g2->overlay.rfb_cb_ref != LUA_NOREF) { + lua_State *L = lua_getstate(); + + lua_rawgeti( L, LUA_REGISTRYINDEX, ext_u8g2->overlay.rfb_cb_ref ); + lua_pushlstring( L, (const char *)fbrle_line, fbrle_line_size ); + lua_call( L, 1, 0 ); + } + } + + free( fbrle_line ); + } + break; + + default: + return 0; + break; + } + + return 1; +} + +uint8_t u8x8_d_overlay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + uint8_t res = 1; + u8g2_nodemcu_t *ext_u8g2 = (u8g2_nodemcu_t *)u8x8; + + switch(msg) + { + case U8X8_MSG_DISPLAY_SETUP_MEMORY: + // only call for hardware display + if (ext_u8g2->overlay.hardware_display_cb) + return ext_u8g2->overlay.hardware_display_cb(u8x8, msg, arg_int, arg_ptr); + break; + + default: + // forward all messages first to hardware display and then to fbrle + if (ext_u8g2->overlay.hardware_display_cb) + res = ext_u8g2->overlay.hardware_display_cb(u8x8, msg, arg_int, arg_ptr); + u8x8_d_fbrle(u8x8, msg, arg_int, arg_ptr); + break; + } + + return res; +} diff --git a/lua_examples/u8g2/graphics_test.lua b/lua_examples/u8g2/graphics_test.lua new file mode 100644 index 00000000..2e394682 --- /dev/null +++ b/lua_examples/u8g2/graphics_test.lua @@ -0,0 +1,263 @@ +-- *************************************************************************** +-- Graphics Test +-- +-- This script executes several features of u8glib to test their Lua bindings. +-- +-- Note: It is prepared for SSD1306-based displays. Select your connectivity +-- type by calling either init_i2c_display() or init_spi_display() at +-- the bottom of this file. +-- +-- *************************************************************************** + +-- setup I2c and connect display +function init_i2c_display() + -- SDA and SCL can be assigned freely to available GPIOs + local sda = 5 -- GPIO14 + local scl = 6 -- GPIO12 + local sla = 0x3c + i2c.setup(0, sda, scl, i2c.SLOW) + disp = u8g2.ssd1306_i2c_128x64_noname(0, sla) +end + +-- setup SPI and connect display +function init_spi_display() + -- Hardware SPI CLK = GPIO14 + -- Hardware SPI MOSI = GPIO13 + -- Hardware SPI MISO = GPIO12 (not used) + -- Hardware SPI /CS = GPIO15 (not used) + -- CS, D/C, and RES can be assigned freely to available GPIOs + local cs = 8 -- GPIO15, pull-down 10k to GND + local dc = 4 -- GPIO2 + local res = 0 -- GPIO16 + + spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8) + -- we won't be using the HSPI /CS line, so disable it again + gpio.mode(8, gpio.INPUT, gpio.PULLUP) + + disp = u8g2.ssd1306_128x64_noname(1, cs, dc, res) +end + + +function u8g2_prepare() + disp:setFont(u8g2.font_6x10_tf) + disp:setFontRefHeightExtendedText() + disp:setDrawColor(1) + disp:setFontPosTop() + disp:setFontDirection(0) +end + + +function u8g2_box_frame(a) + disp:drawStr( 0, 0, "drawBox") + disp:drawBox(5,10,20,10) + disp:drawBox(10+a,15,30,7) + disp:drawStr( 0, 30, "drawFrame") + disp:drawFrame(5,10+30,20,10) + disp:drawFrame(10+a,15+30,30,7) +end + +function u8g2_disc_circle(a) + disp:drawStr( 0, 0, "drawDisc") + disp:drawDisc(10,18,9) + disp:drawDisc(24+a,16,7) + disp:drawStr( 0, 30, "drawCircle") + disp:drawCircle(10,18+30,9) + disp:drawCircle(24+a,16+30,7) +end + +function u8g2_r_frame(a) + disp:drawStr( 0, 0, "drawRFrame/Box") + disp:drawRFrame(5, 10,40,30, a+1) + disp:drawRBox(50, 10,25,40, a+1) +end + +function u8g2_string(a) + disp:setFontDirection(0) + disp:drawStr(30+a,31, " 0") + disp:setFontDirection(1) + disp:drawStr(30,31+a, " 90") + disp:setFontDirection(2) + disp:drawStr(30-a,31, " 180") + disp:setFontDirection(3) + disp:drawStr(30,31-a, " 270") +end + +function u8g2_line(a) + disp:drawStr( 0, 0, "drawLine") + disp:drawLine(7+a, 10, 40, 55) + disp:drawLine(7+a*2, 10, 60, 55) + disp:drawLine(7+a*3, 10, 80, 55) + disp:drawLine(7+a*4, 10, 100, 55) +end + +function u8g2_triangle(a) + local offset = a + disp:drawStr( 0, 0, "drawTriangle") + disp:drawTriangle(14,7, 45,30, 10,40) + disp:drawTriangle(14+offset,7-offset, 45+offset,30-offset, 57+offset,10-offset) + disp:drawTriangle(57+offset*2,10, 45+offset*2,30, 86+offset*2,53) + disp:drawTriangle(10+offset,40+offset, 45+offset,30+offset, 86+offset,53+offset) +end + +function u8g2_ascii_1() + disp:drawStr( 0, 0, "ASCII page 1") + for y = 0, 5 do + for x = 0, 15 do + disp:drawStr(x*7, y*10+10, string.char(y*16 + x + 32)) + end + end +end + +function u8g2_ascii_2() + disp:drawStr( 0, 0, "ASCII page 2") + for y = 0, 5 do + for x = 0, 15 do + disp:drawStr(x*7, y*10+10, string.char(y*16 + x + 160)) + end + end +end + +function u8g2_extra_page(a) + disp:drawStr( 0, 0, "Unicode") + disp:setFont(u8g2.font_unifont_t_symbols) + disp:setFontPosTop() + disp:drawUTF8(0, 24, "☀ ☁") + if a <= 3 then + disp:drawUTF8(a*3, 36, "☂") + else + disp:drawUTF8(a*3, 36, "☔") + end +end + +cross_width = 24 +cross_height = 24 +cross_bits = string.char( + 0x00, 0x18, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x42, 0x00, + 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, + 0xC0, 0x00, 0x03, 0x38, 0x3C, 0x1C, 0x06, 0x42, 0x60, 0x01, 0x42, 0x80, + 0x01, 0x42, 0x80, 0x06, 0x42, 0x60, 0x38, 0x3C, 0x1C, 0xC0, 0x00, 0x03, + 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, + 0x00, 0x42, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x18, 0x00) + +cross_fill_width = 24 +cross_fill_height = 24 +cross_fill_bits = string.char( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x64, 0x00, 0x26, + 0x84, 0x00, 0x21, 0x08, 0x81, 0x10, 0x08, 0x42, 0x10, 0x10, 0x3C, 0x08, + 0x20, 0x00, 0x04, 0x40, 0x00, 0x02, 0x80, 0x00, 0x01, 0x80, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x00, 0x01, 0x40, 0x00, 0x02, 0x20, 0x00, 0x04, + 0x10, 0x3C, 0x08, 0x08, 0x42, 0x10, 0x08, 0x81, 0x10, 0x84, 0x00, 0x21, + 0x64, 0x00, 0x26, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +cross_block_width = 14 +cross_block_height = 14 +cross_block_bits = string.char( + 0xFF, 0x3F, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, + 0xC1, 0x20, 0xC1, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, + 0x01, 0x20, 0xFF, 0x3F) + +function u8g2_bitmap_overlay(a) + local frame_size = 28 + + disp:drawStr(0, 0, "Bitmap overlay") + + disp:drawStr(0, frame_size + 12, "Solid / transparent") + disp:setBitmapMode(0) -- solid + disp:drawFrame(0, 10, frame_size, frame_size) + disp:drawXBM(2, 12, cross_width, cross_height, cross_bits) + if bit.band(a, 4) > 0 then + disp:drawXBM(7, 17, cross_block_width, cross_block_height, cross_block_bits) + end + + disp:setBitmapMode(1) -- transparent + disp:drawFrame(frame_size + 5, 10, frame_size, frame_size) + disp:drawXBM(frame_size + 7, 12, cross_width, cross_height, cross_bits) + if bit.band(a, 4) then + disp:drawXBM(frame_size + 12, 17, cross_block_width, cross_block_height, cross_block_bits) + end +end + +function u8g2_bitmap_modes(transparent) + local frame_size = 24 + + disp:drawBox(0, frame_size * 0.5, frame_size * 5, frame_size) + disp:drawStr(frame_size * 0.5, 50, "Black") + disp:drawStr(frame_size * 2, 50, "White") + disp:drawStr(frame_size * 3.5, 50, "XOR") + + if transparent == 0 then + disp:setBitmapMode(0) -- solid + disp:drawStr(0, 0, "Solid bitmap") + else + disp:setBitmapMode(1) -- transparent + disp:drawStr(0, 0, "Transparent bitmap") + end + disp:setDrawColor(0) -- Black + disp:drawXBM(frame_size * 0.5, 24, cross_width, cross_height, cross_bits) + disp:setDrawColor(1) -- White + disp:drawXBM(frame_size * 2, 24, cross_width, cross_height, cross_bits) + disp:setDrawColor(2) -- XOR + disp:drawXBM(frame_size * 3.5, 24, cross_width, cross_height, cross_bits) +end + + +function draw() + u8g2_prepare() + + local d3 = bit.rshift(draw_state, 3) + local d7 = bit.band(draw_state, 7) + + if d3 == 0 then + u8g2_box_frame(d7) + elseif d3 == 1 then + u8g2_disc_circle(d7) + elseif d3 == 2 then + u8g2_r_frame(d7) + elseif d3 == 3 then + u8g2_string(d7) + elseif d3 == 4 then + u8g2_line(d7) + elseif d3 == 5 then + u8g2_triangle(d7) + elseif d3 == 6 then + u8g2_ascii_1() + elseif d3 == 7 then + u8g2_ascii_2() + elseif d3 == 8 then + u8g2_extra_page(d7) + elseif d3 == 9 then + u8g2_bitmap_modes(0) + elseif d3 == 10 then + u8g2_bitmap_modes(1) + elseif d3 == 11 then + u8g2_bitmap_overlay(d7) + end +end + + +function loop() + -- picture loop + disp:clearBuffer() + draw() + disp:sendBuffer() + + -- increase the state + draw_state = draw_state + 1 + if draw_state >= 12*8 then + draw_state = 0 + end + + -- delay between each frame + loop_tmr:start() +end + + +draw_state = 0 +loop_tmr = tmr.create() +loop_tmr:register(100, tmr.ALARM_SEMI, loop) + +init_i2c_display() +--init_spi_display() + +print("--- Starting Graphics Test ---") +loop_tmr:start() diff --git a/lua_examples/u8glib/u8g_bitmaps.lua b/lua_examples/u8glib/u8g_bitmaps.lua deleted file mode 100644 index 300aa9bb..00000000 --- a/lua_examples/u8glib/u8g_bitmaps.lua +++ /dev/null @@ -1,115 +0,0 @@ --- *************************************************************************** --- Bitmaps Test --- --- This script executes the bitmap features of u8glib to test their Lua --- integration. --- --- Note: It is prepared for SSD1306-based displays. Select your connectivity --- type by calling either init_i2c_display() or init_spi_display() at --- the bottom of this file. --- --- *************************************************************************** - --- setup I2c and connect display -function init_i2c_display() - -- SDA and SCL can be assigned freely to available GPIOs - local sda = 5 -- GPIO14 - local scl = 6 -- GPIO12 - local sla = 0x3c - i2c.setup(0, sda, scl, i2c.SLOW) - disp = u8g.ssd1306_128x64_i2c(sla) -end - --- setup SPI and connect display -function init_spi_display() - -- Hardware SPI CLK = GPIO14 - -- Hardware SPI MOSI = GPIO13 - -- Hardware SPI MISO = GPIO12 (not used) - -- Hardware SPI /CS = GPIO15 (not used) - -- CS, D/C, and RES can be assigned freely to available GPIOs - local cs = 8 -- GPIO15, pull-down 10k to GND - local dc = 4 -- GPIO2 - local res = 0 -- GPIO16 - - spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8) - -- we won't be using the HSPI /CS line, so disable it again - gpio.mode(8, gpio.INPUT, gpio.PULLUP) - - disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res) -end - - -function xbm_picture() - disp:setFont(u8g.font_6x10) - disp:drawStr( 0, 10, "XBM picture") - - disp:drawXBM( 0, 20, 38, 24, xbm_data ) -end - -function bitmap_picture(state) - disp:setFont(u8g.font_6x10) - disp:drawStr( 0, 10, "Bitmap picture") - - disp:drawBitmap( 0 + (state * 10), 20 + (state * 4), 1, 8, bm_data ) -end - --- the draw() routine -function draw(draw_state) - local component = bit.rshift(draw_state, 3) - - if (component == 0) then - xbm_picture(bit.band(draw_state, 7)) - elseif (component == 1) then - bitmap_picture(bit.band(draw_state, 7)) - end -end - - -function draw_loop() - -- Draws one page and schedules the next page, if there is one - local function draw_pages() - draw(draw_state) - if disp:nextPage() then - node.task.post(draw_pages) - else - node.task.post(bitmap_test) - end - end - -- Restart the draw loop and start drawing pages - disp:firstPage() - node.task.post(draw_pages) -end - -function bitmap_test() - - if (draw_state <= 7 + 1*8) then - draw_state = draw_state + 1 - else - print("--- Restarting Bitmap Test ---") - draw_state = 1 - end - - print("Heap: " .. node.heap()) - -- retrigger draw_loop - node.task.post(draw_loop) - -end - -draw_state = 1 - -init_i2c_display() ---init_spi_display() - --- read XBM picture -file.open("u8glib_logo.xbm", "r") -xbm_data = file.read() -file.close() - --- read Bitmap picture -file.open("u8g_rook.bm", "r") -bm_data = file.read() -file.close() - - -print("--- Starting Bitmap Test ---") -node.task.post(draw_loop) diff --git a/lua_examples/u8glib/u8g_drawloop.lua b/lua_examples/u8glib/u8g_drawloop.lua deleted file mode 100644 index a8184fd1..00000000 --- a/lua_examples/u8glib/u8g_drawloop.lua +++ /dev/null @@ -1,73 +0,0 @@ ------------------------------------------------------------------------------- --- u8glib example which shows how to implement the draw loop without causing --- timeout issues with the WiFi stack. This is done by drawing one page at --- a time, allowing the ESP SDK to do its house keeping between the page --- draws. --- --- This example assumes you have an SSD1306 display connected to pins 4 and 5 --- using I2C and that the profont22r is compiled into the firmware. --- Please edit the init_display function to match your setup. --- --- Example: --- dofile("u8g_drawloop.lua") ------------------------------------------------------------------------------- - -local disp -local font - -function init_display() - local sda = 4 - local sdl = 5 - local sla = 0x3c - i2c.setup(0,sda,sdl, i2c.SLOW) - disp = u8g.ssd1306_128x64_i2c(sla) - font = u8g.font_profont22r -end - -local function setLargeFont() - disp:setFont(font) - disp:setFontRefHeightExtendedText() - disp:setDefaultForegroundColor() - disp:setFontPosTop() -end - --- Start the draw loop with the draw implementation in the provided function callback -function updateDisplay(func) - -- Draws one page and schedules the next page, if there is one - local function drawPages() - func() - if (disp:nextPage() == true) then - node.task.post(drawPages) - end - end - -- Restart the draw loop and start drawing pages - disp:firstPage() - node.task.post(drawPages) -end - -function drawHello() - setLargeFont() - disp:drawStr(30,22, "Hello") -end - -function drawWorld() - setLargeFont() - disp:drawStr(30,22, "World") -end - -local drawDemo = { drawHello, drawWorld } - -function demoLoop() - -- Start the draw loop with one of the demo functions - local f = table.remove(drawDemo,1) - updateDisplay(f) - table.insert(drawDemo,f) -end - --- Initialise the display -init_display() - --- Draw demo page immediately and then schedule an update every 5 seconds. --- To test your own drawXYZ function, disable the next two lines and call updateDisplay(drawXYZ) instead. -demoLoop() -tmr.alarm(4, 5000, 1, demoLoop) diff --git a/lua_examples/u8glib/u8g_graphics_test.lua b/lua_examples/u8glib/u8g_graphics_test.lua deleted file mode 100644 index 640e56ae..00000000 --- a/lua_examples/u8glib/u8g_graphics_test.lua +++ /dev/null @@ -1,177 +0,0 @@ --- *************************************************************************** --- Graphics Test --- --- This script executes several features of u8glib to test their Lua bindings. --- --- Note: It is prepared for SSD1306-based displays. Select your connectivity --- type by calling either init_i2c_display() or init_spi_display() at --- the bottom of this file. --- --- *************************************************************************** - --- setup I2c and connect display -function init_i2c_display() - -- SDA and SCL can be assigned freely to available GPIOs - local sda = 5 -- GPIO14 - local scl = 6 -- GPIO12 - local sla = 0x3c - i2c.setup(0, sda, scl, i2c.SLOW) - disp = u8g.ssd1306_128x64_i2c(sla) -end - --- setup SPI and connect display -function init_spi_display() - -- Hardware SPI CLK = GPIO14 - -- Hardware SPI MOSI = GPIO13 - -- Hardware SPI MISO = GPIO12 (not used) - -- Hardware SPI /CS = GPIO15 (not used) - -- CS, D/C, and RES can be assigned freely to available GPIOs - local cs = 8 -- GPIO15, pull-down 10k to GND - local dc = 4 -- GPIO2 - local res = 0 -- GPIO16 - - spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8) - -- we won't be using the HSPI /CS line, so disable it again - gpio.mode(8, gpio.INPUT, gpio.PULLUP) - - disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res) -end - - --- graphic test components -function prepare() - disp:setFont(u8g.font_6x10) - disp:setFontRefHeightExtendedText() - disp:setDefaultForegroundColor() - disp:setFontPosTop() -end - -function box_frame(a) - disp:drawStr(0, 0, "drawBox") - disp:drawBox(5, 10, 20, 10) - disp:drawBox(10+a, 15, 30, 7) - disp:drawStr(0, 30, "drawFrame") - disp:drawFrame(5, 10+30, 20, 10) - disp:drawFrame(10+a, 15+30, 30, 7) -end - -function disc_circle(a) - disp:drawStr(0, 0, "drawDisc") - disp:drawDisc(10, 18, 9) - disp:drawDisc(24+a, 16, 7) - disp:drawStr(0, 30, "drawCircle") - disp:drawCircle(10, 18+30, 9) - disp:drawCircle(24+a, 16+30, 7) -end - -function r_frame(a) - disp:drawStr(0, 0, "drawRFrame/Box") - disp:drawRFrame(5, 10, 40, 30, a+1) - disp:drawRBox(50, 10, 25, 40, a+1) -end - -function stringtest(a) - disp:drawStr(30+a, 31, " 0") - disp:drawStr90(30, 31+a, " 90") - disp:drawStr180(30-a, 31, " 180") - disp:drawStr270(30, 31-a, " 270") -end - -function line(a) - disp:drawStr(0, 0, "drawLine") - disp:drawLine(7+a, 10, 40, 55) - disp:drawLine(7+a*2, 10, 60, 55) - disp:drawLine(7+a*3, 10, 80, 55) - disp:drawLine(7+a*4, 10, 100, 55) -end - -function triangle(a) - local offset = a - disp:drawStr(0, 0, "drawTriangle") - disp:drawTriangle(14,7, 45,30, 10,40) - disp:drawTriangle(14+offset,7-offset, 45+offset,30-offset, 57+offset,10-offset) - disp:drawTriangle(57+offset*2,10, 45+offset*2,30, 86+offset*2,53) - disp:drawTriangle(10+offset,40+offset, 45+offset,30+offset, 86+offset,53+offset) -end - -function ascii_1() - local x, y, s - disp:drawStr(0, 0, "ASCII page 1") - for y = 0, 5, 1 do - for x = 0, 15, 1 do - s = y*16 + x + 32 - disp:drawStr(x*7, y*10+10, string.char(s)) - end - end -end - -function extra_page(a) - disp:drawStr(0, 12, "setScale2x2") - disp:setScale2x2() - disp:drawStr(0, 6+a, "setScale2x2") - disp:undoScale() -end - - --- the draw() routine -function draw(draw_state) - local component = bit.rshift(draw_state, 3) - - prepare() - - if (component == 0) then - box_frame(bit.band(draw_state, 7)) - elseif (component == 1) then - disc_circle(bit.band(draw_state, 7)) - elseif (component == 2) then - r_frame(bit.band(draw_state, 7)) - elseif (component == 3) then - stringtest(bit.band(draw_state, 7)) - elseif (component == 4) then - line(bit.band(draw_state, 7)) - elseif (component == 5) then - triangle(bit.band(draw_state, 7)) - elseif (component == 6) then - ascii_1() - elseif (component == 7) then - extra_page(bit.band(draw_state, 7)) - end -end - -function draw_loop() - -- Draws one page and schedules the next page, if there is one - local function draw_pages() - draw(draw_state) - if disp:nextPage() then - node.task.post(draw_pages) - else - node.task.post(graphics_test) - end - end - -- Restart the draw loop and start drawing pages - disp:firstPage() - node.task.post(draw_pages) -end - -function graphics_test() - - if (draw_state <= 7 + 8*8) then - draw_state = draw_state + 1 - else - print("--- Restarting Graphics Test ---") - draw_state = 0 - end - - print("Heap: " .. node.heap()) - -- retrigger draw_loop - node.task.post(draw_loop) - -end - -draw_state = 0 - -init_i2c_display() ---init_spi_display() - -print("--- Starting Graphics Test ---") -node.task.post(draw_loop) diff --git a/lua_examples/u8glib/u8g_rook.bm b/lua_examples/u8glib/u8g_rook.bm deleted file mode 100644 index 9dd93966f264609e124d1438e97c63b29a56c805..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8 NcmZPwt+xY$dH@MH0!#n^ diff --git a/lua_examples/u8glib/u8g_rotation.lua b/lua_examples/u8glib/u8g_rotation.lua deleted file mode 100644 index 5ee4b1c3..00000000 --- a/lua_examples/u8glib/u8g_rotation.lua +++ /dev/null @@ -1,97 +0,0 @@ --- *************************************************************************** --- Rotation Test --- --- This script executes the rotation features of u8glib to test their Lua --- integration. --- --- Note: It is prepared for SSD1306-based displays. Select your connectivity --- type by calling either init_i2c_display() or init_spi_display() at --- the bottom of this file. --- --- *************************************************************************** - --- setup I2c and connect display -function init_i2c_display() - -- SDA and SCL can be assigned freely to available GPIOs - local sda = 5 -- GPIO14 - local scl = 6 -- GPIO12 - local sla = 0x3c - i2c.setup(0, sda, scl, i2c.SLOW) - disp = u8g.ssd1306_128x64_i2c(sla) -end - --- setup SPI and connect display -function init_spi_display() - -- Hardware SPI CLK = GPIO14 - -- Hardware SPI MOSI = GPIO13 - -- Hardware SPI MISO = GPIO12 (not used) - -- Hardware SPI /CS = GPIO15 (not used) - -- CS, D/C, and RES can be assigned freely to available GPIOs - local cs = 8 -- GPIO15, pull-down 10k to GND - local dc = 4 -- GPIO2 - local res = 0 -- GPIO16 - - spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8) - -- we won't be using the HSPI /CS line, so disable it again - gpio.mode(8, gpio.INPUT, gpio.PULLUP) - - disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res) -end - - --- the draw() routine -function draw() - disp:setFont(u8g.font_6x10) - disp:drawStr( 0+0, 20+0, "Hello!") - disp:drawStr( 0+2, 20+16, "Hello!") - - disp:drawBox(0, 0, 3, 3) - disp:drawBox(disp:getWidth()-6, 0, 6, 6) - disp:drawBox(disp:getWidth()-9, disp:getHeight()-9, 9, 9) - disp:drawBox(0, disp:getHeight()-12, 12, 12) -end - - -function rotate() - if (next_rotation < tmr.now() / 1000) then - if (dir == 0) then - disp:undoRotation() - elseif (dir == 1) then - disp:setRot90() - elseif (dir == 2) then - disp:setRot180() - elseif (dir == 3) then - disp:setRot270() - end - - dir = dir + 1 - dir = bit.band(dir, 3) - -- schedule next rotation step in 1000ms - next_rotation = tmr.now() / 1000 + 1000 - end -end - -function rotation_test() - print("--- Starting Rotation Test ---") - dir = 0 - next_rotation = 0 - - local loopcnt - for loopcnt = 1, 100, 1 do - rotate() - - disp:firstPage() - repeat - draw(draw_state) - until disp:nextPage() == false - - tmr.delay(100000) - tmr.wdclr() - end - - print("--- Rotation Test done ---") -end - ---init_i2c_display() -init_spi_display() -rotation_test() diff --git a/lua_examples/u8glib/u8glib_logo.xbm b/lua_examples/u8glib/u8glib_logo.xbm deleted file mode 100644 index 876c4b7ca11b4f3da9e39271fc9facbf40c5491d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmezW|Nnn`ApURv-~o_${18Zd{s<=i?Kl4{C?jw1nUSMM;WHz{0n5*g#}8V5K6w13 z#pi>EC2byeGS09+F2TTI$8S?0V_^UPPrKp&|ND