Browse Source

Add u8g2 module.

devsaurus 7 years ago
parent
commit
a8ff8f059d

+ 3 - 0
.gitmodules

@@ -5,3 +5,6 @@
 	path = sdk/esp32-esp-idf
 	url = https://github.com/espressif/esp-idf.git
   ignore = dirty
+[submodule "components/u8g2/u8g2"]
+	path = components/u8g2/u8g2
+	url = https://github.com/olikraus/U8g2_Arduino.git

+ 8 - 0
components/modules/Kconfig

@@ -154,6 +154,14 @@ config LUA_MODULE_TMR
   help
       Includes the timer module (recommended).
 
+config LUA_MODULE_U8G2
+  bool "U8G2 module"
+  default "n"
+  help
+      Includes the u8g2 module.
+
+source "../components/u8g2/u8g2.kconfig"
+
 config LUA_MODULE_WIFI
   bool "WiFi module"
   default "y"

+ 10 - 0
components/modules/component.mk

@@ -21,3 +21,13 @@ CFLAGS += \
 	-Werror=unused-function \
 	-Werror=unused-but-set-variable \
 	-Werror=unused-variable \
+
+COMPONENT_EXTRA_CLEAN := u8g2_fonts.h u8g2_displays.h
+
+u8g2.o: u8g2_fonts.h u8g2_displays.h
+
+u8g2_fonts.h: $(BUILD_DIR_BASE)/include/sdkconfig.h
+	perl -w $(PROJECT_PATH)/tools/u8g2_config_fonts.pl < $^ > $@
+
+u8g2_displays.h: $(BUILD_DIR_BASE)/include/sdkconfig.h
+	perl -w $(PROJECT_PATH)/tools/u8g2_config_displays.pl < $^ > $@

+ 4 - 0
components/modules/spi_common.h

@@ -4,6 +4,10 @@
 
 #include "lauxlib.h"
 
+typedef struct {
+  int host;
+} lspi_host_t;
+
 // ***************************************************************************
 // SPI master
 //

+ 2 - 4
components/modules/spi_master.c

@@ -10,6 +10,8 @@
 
 #include "esp_log.h"
 
+#include "spi_common.h"
+
 #define SPI_MASTER_TAG "spi.master"
 
 #define UD_HOST_STR "spi.master"
@@ -188,10 +190,6 @@ static const LUA_REG_TYPE lspi_device_map[] = {
 // ****************************************************************************
 // Host related functions
 //
-typedef struct {
-  int host;
-} lspi_host_t;
-
 #define GET_UD_HOST \
   lspi_host_t *ud = (lspi_host_t *)luaL_checkudata( L, 1, UD_HOST_STR );
 //

+ 696 - 0
components/modules/u8g2.c

@@ -0,0 +1,696 @@
+// Module for binding the u8g2 library
+
+#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"
+
+#include "spi_common.h"
+
+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}
+};
+
+
+
+// ***************************************************************************
+// Device constructors
+//
+//
+// I2C based devices will use this function template to implement the Lua binding.
+#undef U8G2_DISPLAY_TABLE_ENTRY
+#define U8G2_DISPLAY_TABLE_ENTRY(function, binding)                     \
+  static int l ## binding( lua_State *L )                               \
+  {                                                                     \
+    int stack = 0;                                                      \
+                                                                        \
+    int id = luaL_checkint( L, ++stack );                 \
+                                                                        \
+    int i2c_addr = luaL_checkint( L, ++stack );                         \
+    luaL_argcheck( L, i2c_addr >= 0 && i2c_addr <= 0x7f, stack, "invalid i2c address" ); \
+                                                                        \
+    u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) ); \
+    u8g2_nodemcu_t *u8g2 = &(ud->u8g2);                                 \
+    ud->font_ref = LUA_NOREF;                                           \
+    ud->host_ref = LUA_NOREF;                                           \
+    /* the i2c driver id is forwarded in the hal member */              \
+    u8g2->hal = (void *)id;                                             \
+                                                                        \
+    function( (u8g2_t *)u8g2, U8G2_R0, u8x8_byte_nodemcu_i2c, u8x8_gpio_and_delay_nodemcu ); \
+    u8x8_SetI2CAddress( (u8x8_t *)u8g2, i2c_addr );                     \
+                                                                        \
+    u8g2_InitDisplay( (u8g2_t *)u8g2 );                                 \
+    u8g2_ClearDisplay( (u8g2_t *)u8g2 );                                \
+    u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 );                             \
+                                                                        \
+    /* set its metatable */                                             \
+    luaL_getmetatable(L, "u8g2.display");                               \
+    lua_setmetatable(L, -2);                                            \
+                                                                        \
+    return 1;                                                           \
+  }
+//
+// Unroll the display table and insert binding functions for I2C based displays.
+U8G2_DISPLAY_TABLE_I2C
+//
+//
+//
+
+
+// SPI based devices will use this function template to implement the Lua binding.
+#undef U8G2_DISPLAY_TABLE_ENTRY
+#define U8G2_DISPLAY_TABLE_ENTRY(function, binding)                     \
+  static int l ## binding( lua_State *L )                               \
+  {                                                                     \
+    int stack = 0;                                                      \
+                                                                        \
+    lspi_host_t *host = (lspi_host_t *)luaL_checkudata( L, ++stack, "spi.master" ); \
+    /* reference host object to avoid automatic gc */                   \
+    lua_pushvalue( L, stack );                                          \
+    int host_ref = luaL_ref( L, LUA_REGISTRYINDEX );                    \
+                                                                        \
+    int cs = luaL_checkint( L, ++stack );                               \
+    int dc = luaL_checkint( L, ++stack );                               \
+    int res = luaL_optint( L, ++stack, -1 );                            \
+                                                                        \
+    u8g2_ud_t *ud = (u8g2_ud_t *)lua_newuserdata( L, sizeof( u8g2_ud_t ) ); \
+    u8g2_nodemcu_t *u8g2 = &(ud->u8g2);                                 \
+    ud->font_ref = LUA_NOREF;                                           \
+    ud->host_ref = host_ref;                                            \
+    /* the spi host id is forwarded in the hal member */                \
+    u8g2->hal = (void *)(host->host);                                   \
+                                                                        \
+    function( (u8g2_t *)u8g2, U8G2_R0, u8x8_byte_nodemcu_spi, u8x8_gpio_and_delay_nodemcu ); \
+    u8x8_SetPin( (u8x8_t *)u8g2, U8X8_PIN_CS, cs );                     \
+    u8x8_SetPin( (u8x8_t *)u8g2, U8X8_PIN_DC, dc );                     \
+    if (res >= 0)                                                       \
+      u8x8_SetPin( (u8x8_t *)u8g2, U8X8_PIN_RESET, res );               \
+                                                                        \
+    u8g2_InitDisplay( (u8g2_t *)u8g2 );                                 \
+    u8g2_ClearDisplay( (u8g2_t *)u8g2 );                                \
+    u8g2_SetPowerSave( (u8g2_t *)u8g2, 0 );                             \
+                                                                        \
+    /* set its metatable */                                             \
+    luaL_getmetatable(L, "u8g2.display");                               \
+    lua_setmetatable(L, -2);                                            \
+                                                                        \
+    return 1;                                                           \
+  }
+//
+// 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);

+ 2 - 0
components/platform/component.mk

@@ -1 +1,3 @@
 COMPONENT_ADD_INCLUDEDIRS:=include
+# for u8x8
+CPPFLAGS+=-DU8X8_USE_PINS

+ 19 - 0
components/platform/include/u8x8_nodemcu_hal.h

@@ -0,0 +1,19 @@
+
+#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;
+} 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 */

+ 329 - 0
components/platform/u8x8_nodemcu_hal.c

@@ -0,0 +1,329 @@
+
+#include <string.h>
+
+#include "rom/ets_sys.h"
+
+#include "driver/gpio.h"
+#include "driver/i2c.h"
+#include "driver/spi_master.h"
+#include "platform.h"
+
+#include "u8x8_nodemcu_hal.h"
+
+#include "esp_heap_alloc_caps.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
+        gpio_config_t cfg;
+        memset( (void *)&cfg, 0, sizeof( cfg ) );
+        cfg.pin_bit_mask = 1ULL << u8x8->pins[idx];
+
+        if (idx == U8X8_PIN_I2C_CLOCK || idx == U8X8_PIN_I2C_CLOCK) {
+          cfg.mode = GPIO_MODE_OUTPUT_OD;
+          cfg.pull_up_en = GPIO_PULLUP_ENABLE;
+        } else {
+          cfg.mode = GPIO_MODE_OUTPUT;
+          cfg.pull_up_en = GPIO_PULLUP_DISABLE;
+        }
+        cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
+        cfg.intr_type = GPIO_INTR_DISABLE;
+        gpio_config( &cfg );
+      }
+    }
+    break;
+
+  case U8X8_MSG_DELAY_NANO:           // delay arg_int * 1 nano second
+    ets_delay_us( 1 );
+    break;    
+
+  case U8X8_MSG_DELAY_100NANO:        // delay arg_int * 100 nano seconds
+    temp = arg_int * 100;
+    temp /= 1000;
+    ets_delay_us( temp > 0 ? temp : 1 );
+    break;
+
+  case U8X8_MSG_DELAY_10MICRO:        // delay arg_int * 10 micro seconds
+    ets_delay_us( arg_int * 10 );
+    break;
+
+  case U8X8_MSG_DELAY_MILLI:          // delay arg_int * 1 milli second
+    ets_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;
+    ets_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
+    gpio_set_level( u8x8_GetPinValue( u8x8, msg ), arg_int );
+    break;
+  case U8X8_MSG_GPIO_DC:              // DC (data/cmd, A0, register select) pin: Output level in arg_int
+    gpio_set_level( 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)
+      gpio_set_level( 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
+    gpio_set_level( 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
+    gpio_set_level( 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;
+  i2c_cmd_handle_t cmd;
+  struct {
+    uint8_t *data;
+    size_t size, used;
+  } buffer;
+} 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, 0 );
+        data++;
+        arg_int--;
+      }
+
+    } else {
+      while (hal->buffer.size - hal->buffer.used < arg_int) {
+        hal->buffer.size *= 2;
+        if (!(hal->buffer.data = (uint8_t *)realloc( hal->buffer.data, hal->buffer.size )))
+          return 0;
+      }
+      memcpy( hal->buffer.data + hal->buffer.used, arg_ptr, arg_int );
+      hal->buffer.used += arg_int;
+    }
+
+    break;
+
+  case U8X8_MSG_BYTE_INIT:
+    {
+      // the hal member initially contains the i2c id
+      int id = (int)hal;
+      if (!(hal = 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, 0 );
+
+    } else {
+      hal->buffer.size = 256;
+      if (!(hal->buffer.data = (uint8_t *)malloc( hal->buffer.size )))
+        return 0;
+      hal->buffer.used = 0;
+
+      hal->cmd = i2c_cmd_link_create();
+      i2c_master_start( hal->cmd );
+      i2c_master_write_byte( hal->cmd, u8x8_GetI2CAddress(u8x8) << 1 | I2C_MASTER_WRITE, false );
+    }
+    break;
+
+  case U8X8_MSG_BYTE_END_TRANSFER:
+    if (hal->id == 0) {
+      platform_i2c_send_stop( 0 );
+
+    } else {
+      if (hal->buffer.used > 0)
+        i2c_master_write( hal->cmd, hal->buffer.data, hal->buffer.used, false );
+
+      i2c_master_stop( hal->cmd );
+      i2c_master_cmd_begin(hal->id-1, hal->cmd, portMAX_DELAY );
+
+      if (hal->buffer.data)
+        free( hal->buffer.data );
+      i2c_cmd_link_delete( hal->cmd );
+    }
+    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) {
+    spi_transaction_t trans;
+    memset( &trans, 0, sizeof( trans ) );
+    trans.length = hal->buffer.used * 8;
+    trans.tx_buffer = hal->buffer.data;
+    spi_device_transmit( hal->device, &trans );
+
+    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 = malloc( sizeof ( hal_spi_t ) )))
+        return 0;
+      hal->host = host;
+      ((u8g2_nodemcu_t *)u8x8)->hal = hal;
+
+      // set up the spi device
+      spi_device_interface_config_t config;
+      memset( &config, 0, sizeof( config ) );
+
+      config.spics_io_num = -1;  // CS is controlled by u8x8 gpio mechanism
+      config.mode = u8x8_GetSPIClockPhase( u8x8 ) | (u8x8_GetSPIClockPolarity( u8x8 ) << 1);
+      config.clock_speed_hz = u8x8->display_info->sck_clock_hz;
+      config.queue_size = 1;
+
+      spi_bus_add_device( hal->host, &config, &(hal->device) );
+
+      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 *)pvPortMallocCaps( hal->buffer.size, MALLOC_CAP_DMA )))
+      return 0;
+    hal->buffer.used = 0;
+
+    u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_enable_level );
+    break;
+
+  case U8X8_MSG_BYTE_SEND:
+    while (hal->buffer.size - hal->buffer.used < arg_int) {
+      hal->buffer.size *= 2;
+      uint8_t *tmp;
+      if (!(tmp = (uint8_t *)pvPortMallocCaps( hal->buffer.size, MALLOC_CAP_DMA ))) {
+        free( hal->buffer.data );
+        return 0;
+      }
+      memcpy( tmp, hal->buffer.data, hal->buffer.used );
+      free( hal->buffer.data );
+      hal->buffer.data = tmp;
+    }
+    memcpy( hal->buffer.data + hal->buffer.used, arg_ptr, arg_int );
+    hal->buffer.used += arg_int;
+    break;
+
+  case U8X8_MSG_BYTE_END_TRANSFER:
+    flush_buffer_spi( hal );
+
+    u8x8_gpio_SetCS( u8x8, u8x8->display_info->chip_disable_level );
+
+    if (hal->buffer.data)
+      free( hal->buffer.data );
+    break;
+
+  default:
+    return 0;
+  }
+
+  return 1;
+}

+ 3 - 0
components/u8g2/component.mk

@@ -0,0 +1,3 @@
+COMPONENT_SRCDIRS:=u8g2/src/clib
+COMPONENT_ADD_INCLUDEDIRS:=u8g2/src/clib
+CPPFLAGS+=-DU8X8_USE_PINS

+ 1 - 0
components/u8g2/u8g2

@@ -0,0 +1 @@
+Subproject commit 61728a5003ebbf60f72e07eb8051d509c084f3a5

+ 322 - 0
components/u8g2/u8g2.kconfig

@@ -0,0 +1,322 @@
+menu "Displays"
+     depends on LUA_MODULE_U8G2
+
+menuconfig U8G2_COMM_I2C
+       bool "I2C"
+       select LUA_MODULE_I2C
+       default "y"
+
+config U8G2_I2C_LD7032_60X32
+       depends on U8G2_COMM_I2C
+       bool "ld7032_i2c_60x32"
+       default "n"
+
+config U8G2_I2C_SH1106_128X64_NONAME
+       depends on U8G2_COMM_I2C
+       bool "sh1106_i2c_128x64_noname"
+       default "n"
+
+config U8G2_I2C_SH1106_128X64_VCOMH0
+       depends on U8G2_COMM_I2C
+       bool "sh1106_i2c_128x64_vcomh0"
+       default "n"
+
+config U8G2_I2C_SSD1305_128X32_NONAME
+       depends on U8G2_COMM_I2C
+       bool "ssd1305_i2c_128x32_noname"
+       default "n"
+
+config U8G2_I2C_SSD1306_64X48_ER
+       depends on U8G2_COMM_I2C
+       bool "ssd1306_i2c_64x48_er"
+       default "n"
+
+config U8G2_I2C_SSD1306_128X32_UNIVISION
+       depends on U8G2_COMM_I2C
+       bool "ssd1306_i2c_128x32_univision"
+       default "n"
+
+config U8G2_I2C_SSD1306_128X64_NONAME
+       depends on U8G2_COMM_I2C
+       bool "ssd1306_i2c_128x64_noname"
+       default "y"
+
+config U8G2_I2C_SSD1306_128X64_VCOMH0
+       depends on U8G2_COMM_I2C
+       bool "ssd1306_i2c_128x64_vcomh0"
+       default "n"
+
+config U8G2_I2C_SSD1309_128X64_NONAME0
+       depends on U8G2_COMM_I2C
+       bool "ssd1309_i2c_128x64_noname0"
+       default "n"
+
+config U8G2_I2C_SSD1309_128X64_NONAME2
+       depends on U8G2_COMM_I2C
+       bool "ssd1309_i2c_128x64_noname2"
+       default "n"
+
+config U8G2_I2C_SSD1325_NHD_128X64
+       depends on U8G2_COMM_I2C
+       bool "ssd1325_i2c_nhd_128x64"
+       default "n"
+
+config U8G2_I2C_SSD1327_SEEED_96X96
+       depends on U8G2_COMM_I2C
+       bool "ssd1327_i2c_seeed_96x96"
+       default "n"
+
+config U8G2_I2C_ST7588_JLX12864
+       depends on U8G2_COMM_I2C
+       bool "st7588_i2c_jlx12864"
+       default "n"
+
+config U8G2_I2C_UC1604_JLX19264
+       depends on U8G2_COMM_I2C
+       bool "uc1604_i2c_jlx19264"
+       default "n"
+
+config U8G2_I2C_UC1608_ERC24064
+       depends on U8G2_COMM_I2C
+       bool "uc1608_i2c_erc24064"
+       default "n"
+
+config U8G2_I2C_UC1608_240X128
+       depends on U8G2_COMM_I2C
+       bool "uc1608_i2c_240x128"
+       default "n"
+
+config U8G2_I2C_UC1610_EA_DOGXL160
+       depends on U8G2_COMM_I2C
+       bool "uc1610_i2c_ea_dogxl160"
+       default "n"
+
+config U8G2_I2C_UC1611_EA_DOGM240
+       depends on U8G2_COMM_I2C
+       bool "uc1611_i2c_ea_dogm240"
+       default "n"
+
+config U8G2_I2C_UC1611_EA_DOGXL240
+       depends on U8G2_COMM_I2C
+       bool "uc1611_i2c_ea_dogxl240"
+       default "n"
+
+
+menuconfig U8G2_COMM_SPI
+       bool "SPI"
+       select LUA_MODULE_SPI
+       default "n"
+
+config U8G2_SPI_IST3020_ERC19264
+       depends on U8G2_COMM_SPI
+       bool "ist3020_erc19264"
+       default "n"
+
+config U8G2_SPI_LD7032_60X32
+       depends on U8G2_COMM_SPI
+       bool "ld7032_60x32"
+       default "n"
+
+config U8G2_SPI_LS013B7DH03_128X128
+       depends on U8G2_COMM_SPI
+       bool "ls013b7dh03_128x128"
+       default "n"
+
+config U8G2_SPI_NT7534_TG12864R
+       depends on U8G2_COMM_SPI
+       bool "nt7534_tg12864r"
+       default "n"
+
+config U8G2_SPI_PCD8544_84X48
+       depends on U8G2_COMM_SPI
+       bool "pcd8544_84x48"
+       default "n"
+
+config U8G2_SPI_PCF8812_96X65
+       depends on U8G2_COMM_SPI
+       bool "pcf8812_96x65"
+       default "n"
+
+config U8G2_SPI_SH1106_128X64_NONAME
+       depends on U8G2_COMM_SPI
+       bool "sh1106_128x64_noname"
+       default "n"
+
+config U8G2_SPI_SH1106_128X64_VCOMH0
+       depends on U8G2_COMM_SPI
+       bool "sh1106_128x64_vcomh0"
+       default "n"
+
+config U8G2_SPI_SSD1305_128X32_NONAME
+       depends on U8G2_COMM_SPI
+       bool "ssd1305_128x32_noname"
+       default "n"
+
+config U8G2_SPI_SSD1306_128X32_UNIVISION
+       depends on U8G2_COMM_SPI
+       bool "ssd1306_128x32_univision"
+       default "n"
+
+config U8G2_SPI_SSD1306_128X64_NONAME
+       depends on U8G2_COMM_SPI
+       bool "ssd1306_128x64_noname"
+       default "y"
+
+config U8G2_SPI_SSD1306_128X64_VCOMH0
+       depends on U8G2_COMM_SPI
+       bool "ssd1306_128x64_vcomh0"
+       default "n"
+
+config U8G2_SPI_SSD1306_64X48_ER
+       depends on U8G2_COMM_SPI
+       bool "ssd1306_64x48_er"
+       default "n"
+
+config U8G2_SPI_SSD1309_128X64_NONAME0
+       depends on U8G2_COMM_SPI
+       bool "ssd1309_128x64_noname0"
+       default "n"
+
+config U8G2_SPI_SSD1309_128X64_NONAME2
+       depends on U8G2_COMM_SPI
+       bool "ssd1309_128x64_noname2"
+       default "n"
+
+config U8G2_SPI_SSD1322_NHD_256X64
+       depends on U8G2_COMM_SPI
+       bool "ssd1322_nhd_256x64"
+       default "n"
+
+config U8G2_SPI_SSD1325_NHD_128X64
+       depends on U8G2_COMM_SPI
+       bool "ssd1325_nhd_128x64"
+       default "n"
+
+config U8G2_SPI_SSD1327_SEEED_96X96
+       depends on U8G2_COMM_SPI
+       bool "ssd1327_seeed_96x96"
+       default "n"
+
+config U8G2_SPI_SSD1329_128X96_NONAME
+       depends on U8G2_COMM_SPI
+       bool "ssd1329_128x96_noname"
+       default "n"
+
+config U8G2_SPI_SSD1606_172X72
+       depends on U8G2_COMM_SPI
+       bool "ssd1606_172x72"
+       default "n"
+
+config U8G2_SPI_SSD1607_200X200
+       depends on U8G2_COMM_SPI
+       bool "ssd1607_200x200"
+       default "n"
+
+config U8G2_SPI_ST7565_EA_DOGM128
+       depends on U8G2_COMM_SPI
+       bool "st7565_ea_dogm128"
+       default "n"
+
+config U8G2_SPI_ST7565_EA_DOGM132
+       depends on U8G2_COMM_SPI
+       bool "st7565_ea_dogm132"
+       default "n"
+
+config U8G2_SPI_ST7565_ERC12864
+       depends on U8G2_COMM_SPI
+       bool "st7565_erc12864"
+       default "n"
+
+config U8G2_SPI_ST7565_LM6059
+       depends on U8G2_COMM_SPI
+       bool "st7565_lm6059"
+       default "n"
+
+config U8G2_SPI_ST7565_NHD_C12832
+       depends on U8G2_COMM_SPI
+       bool "st7565_nhd_c12832"
+       default "n"
+
+config U8G2_SPI_ST7565_NHD_C12864
+       depends on U8G2_COMM_SPI
+       bool "st7565_nhd_c12864"
+       default "n"
+
+config U8G2_SPI_ST7565_ZOLEN_128X64
+       depends on U8G2_COMM_SPI
+       bool "st7565_zolen_128x64"
+       default "n"
+
+config U8G2_SPI_ST7567_PI_132X64
+       depends on U8G2_COMM_SPI
+       bool "st7567_pi_132x64"
+       default "n"
+
+config U8G2_SPI_ST7588_JLX12864
+       depends on U8G2_COMM_SPI
+       bool "st7588_jlx12864"
+       default "n"
+
+config U8G2_SPI_ST7920_S_128X64
+       depends on U8G2_COMM_SPI
+       bool "st7920_s_128x64"
+       default "n"
+
+config U8G2_SPI_ST7920_S_192X32
+       depends on U8G2_COMM_SPI
+       bool "st7920_s_192x32"
+       default "n"
+
+config U8G2_SPI_UC1604_JLX19264
+       depends on U8G2_COMM_SPI
+       bool "uc1604_jlx19264"
+       default "n"
+
+config U8G2_SPI_UC1608_240X128
+       depends on U8G2_COMM_SPI
+       bool "uc1608_240x128"
+       default "n"
+
+config U8G2_SPI_UC1608_ERC24064
+       depends on U8G2_COMM_SPI
+       bool "uc1608_erc24064"
+       default "n"
+
+config U8G2_SPI_UC1610_EA_DOGXL160
+       depends on U8G2_COMM_SPI
+       bool "uc1610_ea_dogxl160"
+       default "n"
+
+config U8G2_SPI_UC1611_EA_DOGM240
+       depends on U8G2_COMM_SPI
+       bool "uc1611_ea_dogm240"
+       default "n"
+
+config U8G2_SPI_UC1611_EA_DOGXL240
+       depends on U8G2_COMM_SPI
+       bool "uc1611_ea_dogxl240"
+       default "n"
+
+config U8G2_SPI_UC1701_EA_DOGS102
+       depends on U8G2_COMM_SPI
+       bool "uc1701_ea_dogs102"
+       default "n"
+
+config U8G2_SPI_UC1701_MINI12864
+       depends on U8G2_COMM_SPI
+       bool "uc1701_mini12864"
+       default "n"
+
+endmenu
+
+menu "Fonts"
+     depends on LUA_MODULE_U8G2
+
+config U8G2_FONT_SELECTION
+       depends on LUA_MODULE_U8G2
+       string  "Font list"
+       default "font_6x10_tf"
+       help
+         Enter a comma-separated list of fonts.
+
+endmenu

+ 215 - 0
docs/en/modules/u8g2.md

@@ -0,0 +1,215 @@
+# u8g2 Module
+| Since  | Origin / Contributor  | Maintainer  | Source  |
+| :----- | :-------------------- | :---------- | :------ |
+| 2017-06-02 | [Oli Kraus](https://github.com/olikraus/u8glib), [Arnim Läuger](https://github.com/devsaurus) | [Arnim Läuger](https://github.com/devsaurus) | [u8g2.c](../../../components/u8g2.c)|
+
+U8g2 is a graphics library developed at [olikraus/u8g2](https://github.com/olikraus/u8g2) with support for many different displays. It is the successor of [U8glib](https://github.com/olikraus/u8glib) which is not developed any further.
+
+The NodeMCU firmware supports the following displays in I²C and SPI mode:
+
+- ld7032 60x32
+- sh1106 128x64
+- ssd1305 128x32
+- ssd1306 - 128x32, 128x64, and 64x48 variants
+- ssd1309 128x64
+- ssd1325 128x63
+- ssd1327 96x96
+- st7588 jlx12864
+- uc1604 jlx19264
+- uc1608 - 240x180 and erc24064 variants
+- ux1610 dogxl160
+- uc1611 - dogm240 and dogxl240 variants
+
+SPI only:
+
+- ist3020 erc19264
+- ls013b7dh03 128x128
+- pcd8544 84x48
+- pcf8812 96x65
+- ssd1322 nhd 256x64
+- ssd1329 128x96
+- ssd1606 172x72
+- ssd1607 200x200
+- st7565 - variants dogm128/132, erc12864, lm6059, c12832/c12864, and zolen 128x64
+- st7567 132x64
+- uc1601_c128032
+- uc1604 jlx19264
+- uc1701 - dogs102 and mini12864 variants
+
+This integration is based on [v2.15.2](https://github.com/olikraus/U8g2_Arduino/releases/tag/2.15.2).
+
+## Overview
+### I²C Connection
+Hook up SDA and SCL to any free GPIOs. Eg. [graphics_test.lua](../../../lua_examples/u8glib/u8g_graphics_test.lua) expects SDA=GPIO16 and SCL=GPIO17. They are used to set up nodemcu's I²C driver before accessing the display:
+```lua
+id  = i2c.HW0
+sda = 16
+scl = 17
+i2c.setup(id, sda, scl, i2c.FAST)
+```
+### SPI connection
+Hook up pins to any free GPIOs:
+
+- SCLK
+- MOSI
+- CS
+- D/C
+- RES (optional for some displays)
+
+Again, refer to the initialization sequence eg. in [graphics_test.lua](../../../lua_examples/u8glib/u8g_graphics_test.lua):
+```lua
+sclk = 19
+mosi = 23
+bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
+```
+
+### Library Usage
+The Lua bindings for this library closely follow u8g2's object oriented C++ API. Based on the u8g2 class, you create an object for your display type.
+
+SSD1306 via I²C:
+```lua
+sla = 0x3c
+disp = u8g2.ssd1306_i2c_128x64_noname(id, sla)
+```
+
+SSD1306 via SPI:
+```lua
+cs  = 22
+dc  = 16
+res = 0 -- RES is optional YMMV
+disp = u8g2.ssd1306_128x64_noname(bus, cs, dc, res)
+```
+
+This object provides all of u8g2's methods to control the display. Refer to [graphics_test.lua](../../../lua_examples/u8glib/u8g_graphics_test.lua) to get an impression how this is achieved with Lua code. Visit the [u8g2 homepage](https://github.com/olikraus/u8g2) for technical details.
+
+
+### Displays
+I²C and HW SPI based displays with support in u8g2 can be enabled. To get access to the respective constructors, enable the desired entries for I²C and SPI displays in u8g2's sub-menu (run `make menuconfig`).
+
+### Fonts
+u8g2 comes with a wide range of fonts for small displays. They can be supplied as strings or compiled into the firmware image to decrease the RAM footprint. Simply add the desired fonts to the font selection sub-entry via `make menuconfig`.
+
+They'll become available as `u8g2.<font_name>` in Lua.
+
+### Bitmaps
+XBM bitmaps are supplied as strings to `drawXBM()`. This off-loads all data handling from the u8g2 module to generic methods for binary files. See [graphics_test.lua](../../../lua_examples/u8glib/u8g_graphics_test.lua).
+
+In contrast to the source code based inclusion of XBMs in upstream u8g2 library, it's required to provide precompiled binary files. This can be performed online with [Online-Utility's Image Converter](http://www.online-utility.org/image_converter.jsp): Convert from XBM to MONO format and upload the binary result.
+
+## I²C Display Drivers
+Initialize a display via I²C.
+
+- `u8g2.ld7032_i2c_60x32()`
+- `u8g2.sh1106_i2c_128x64_noname()`
+- `u8g2.sh1106_i2c_128x64_vcomh0()`
+- `u8g2.ssd1305_i2c_128x32_noname()`
+- `u8g2.ssd1306_i2c_64x48_er()`
+- `u8g2.ssd1306_i2c_128x32_univision()`
+- `u8g2.ssd1306_i2c_128x64_noname()`
+- `u8g2.ssd1306_i2c_128x64_vcomh0()`
+- `u8g2.ssd1309_i2c_128x64_noname0()`
+- `u8g2.ssd1309_i2c_128x64_noname2()`
+- `u8g2.ssd1325_i2c_nhd_128x64()`
+- `u8g2.ssd1327_i2c_seeed_96x96()`
+- `u8g2.st7588_i2c_jlx12864()`
+- `u8g2.uc1604_i2c_jlx19264()`
+- `u8g2.uc1608_i2c_erc24064()`
+- `u8g2.uc1608_i2c_240x128()`
+- `u8g2.uc1610_i2c_ea_dogxl160()`
+- `u8g2.uc1611_i2c_ea_dogm240()`
+- `u8g2.uc1611_i2c_ea_dogxl240()`
+
+#### Syntax
+`u8g2.ssd1306_i2c_128x64_noname(id, address)`
+
+#### Parameters
+- `id` i2c interface id, see [i2c module](i2c.md)
+- `address` I²C slave address of display (unshifted)
+
+#### Returns
+u8g2 display object
+
+#### Example
+```lua
+id  = i2c.HW0
+sda = 16
+scl = 17
+sla = 0x3c
+i2c.setup(id, sda, scl, i2c.FAST)
+disp = u8g2.ssd1306_i2c_128x64_noname(id, sla)
+```
+
+## SPI Display Drivers
+Initialize a display via Hardware SPI.
+
+- `u8g2.ist3020_erc19264()`
+- `u8g2.ld7032_60x32()`
+- `u8g2.ls013b7dh03_128x128()`
+- `u8g2.nt7534_tg12864r()`
+- `u8g2.pcd8544_84x48()`
+- `u8g2.pcf8812_96x65()`
+- `u8g2.sh1106_128x64_noname()`
+- `u8g2.sh1106_128x64_vcomh0()`
+- `u8g2.ssd1305_128x32_noname()`
+- `u8g2.ssd1306_128x32_univision()`
+- `u8g2.ssd1306_128x64_noname()`
+- `u8g2.ssd1306_128x64_vcomh0()`
+- `u8g2.ssd1306_64x48_er()`
+- `u8g2.ssd1309_128x64_noname0()`
+- `u8g2.ssd1309_128x64_noname2()`
+- `u8g2.ssd1322_nhd_256x64()`
+- `u8g2.ssd1325_nhd_128x64()`
+- `u8g2.ssd1327_seeed_96x96()`
+- `u8g2.ssd1329_128x96_noname()`
+- `u8g2.ssd1606_172x72()`
+- `u8g2.ssd1607_200x200()`
+- `u8g2.st7565_ea_dogm128()`
+- `u8g2.st7565_ea_dogm132()`
+- `u8g2.st7565_erc12864()`
+- `u8g2.st7565_lm6059()`
+- `u8g2.st7565_nhd_c12832()`
+- `u8g2.st7565_nhd_c12864()`
+- `u8g2.st7565_zolen_128x64()`
+- `u8g2.st7567_pi_132x64()`
+- `u8g2.st7588_jlx12864()`
+- `u8g2.st7920_s_128x64()`
+- `u8g2.st7920_s_192x32()`
+- `u8g2.uc1604_jlx19264()`
+- `u8g2.uc1608_240x128()`
+- `u8g2.uc1608_erc24064()`
+- `u8g2.uc1610_ea_dogxl160()`
+- `u8g2.uc1611_ea_dogm240()`
+- `u8g2.uc1611_ea_dogxl240()`
+- `u8g2.uc1701_ea_dogs102()`
+- `u8g2.uc1701_mini12864()`
+
+#### Syntax
+`u8g2.ssd1306_128x64_noname(cs, dc[, res])`
+
+#### Parameters
+- `cs` GPIO pin for CS
+- `dc` GPIO pin for DC
+- `res` GPIO pin for RES, none if omitted
+
+#### Returns
+u8g2 display object
+
+#### Example
+```lua
+sclk = 19
+mosi = 23
+cs   = 22
+dc   = 16
+res  = 17
+bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
+disp = u8g2.ssd1306_128x64_noname(bus, cs, dc, res)
+```
+
+## Constants
+Constants for various functions.
+
+`u8g2.DRAW_UPPER_RIGHT`, `u8g2.DRAW_UPPER_LEFT`, `u8g2.DRAW_LOWER_RIGHT`, `u8g2.DRAW_LOWER_LEFT`, `u8g2.DRAW_ALL`,
+
+`u8g2.R0`, `u8g2.R1`, `u8g2.R2`, `u8g2.R3`, `u8g2.MIRROR`,
+
+`u8g2.font_6x10`, ...

+ 208 - 0
docs/en/modules/u8g2_disp.md

@@ -0,0 +1,208 @@
+# u8g2.disp Sub-Module
+
+## u8g2.disp:clearBuffer()
+Clears all pixel in the memory frame buffer.
+
+See [u8g2 clearBuffer()](https://github.com/olikraus/u8g2/wiki/u8g2reference#clearbuffer).
+
+## u8g2.disp:drawBox()
+Draw a box (filled frame).
+
+See [u8g2 drawBox()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawbox).
+
+## u8g2.disp:drawCircle()
+Draw a circle.
+
+See [u8g2 drawCircle()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawcircle).
+
+Note that parameter `opt` is optional and defaults to `u8g2.DRAW_ALL` if omitted.
+
+## u8g2.disp:drawDisc()
+Draw a filled circle.
+
+See [u8g2 drawDisc()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawdisc).
+
+Note that parameter `opt` is optional and defaults to `u8g2.DRAW_ALL` if omitted.
+
+## u8g2.disp:drawEllipse()
+Draw an ellipse.
+
+See [u8g2 drawEllipse()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawellipse).
+
+Note that parameter `opt` is optional and defaults to `u8g2.DRAW_ALL` if omitted.
+
+## u8g2.disp:drawFilledEllipse()
+Draw a filled ellipse.
+
+See [u8g2 drawFilledEllipse()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawfilledellipse).
+
+Note that parameter `opt` is optional and defaults to `u8g2.DRAW_ALL` if omitted.
+
+## u8g2.disp:drawFrame()
+Draw a frame (empty box).
+
+See [u8g2 drawFrame()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawframe).
+
+## u8g2.disp:drawGlyph()
+Draw a single character.
+
+See [u8g2 drawGlyph()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawglyph).
+
+## u8g2.disp:drawHLine()
+Draw a horizontal line.
+
+See [u8g2 drawHLine()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawhline).
+
+## u8g2.disp:drawLine()
+Draw a line between two points.
+
+See [u8g2 drawLine()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawline).
+
+## u8g2.disp:drawPixel()
+Draw a pixel.
+
+See [u8g2 drawPixel()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawpixel).
+
+## u8g2.disp:drawRBox()
+Draw a box with round edges.
+
+See [u8g2 drawRBox()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawrbox).
+
+## u8g2.disp:drawRFrame()
+Draw a frame with round edges.
+
+See [u8g2 drawRFrame()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawrframe).
+
+## u8g2.disp:drawStr()
+Draw a string.
+
+See [u8g2 drawStr()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawstr).
+
+## u8g2.disp:drawTriangle()
+Draw a triangle (filled polygon).
+
+See [u8g2 drawTriangle()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawtriangle).
+
+## u8g2.disp:drawUTF8()
+Draw a string which is encoded as UTF-8.
+
+See [u8g2 drawUTF8()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawutf8).
+
+## u8g2.disp:drawVLine()
+Draw a vertical line.
+
+See [u8g2 drawVLine()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawvline).
+
+## u8g2.disp:drawXBM()
+Draw a XBM Bitmap.
+
+See [u8g2 drawXBM()](https://github.com/olikraus/u8g2/wiki/u8g2reference#drawxbm).
+
+XBM bitmaps are supplied as strings to `drawXBM()`. This off-loads all data handling from the u8g2 module to generic methods for binary files. See [graphics_test.lua](../../../lua_examples/u8glib/u8g_graphics_test.lua).
+
+In contrast to the source code based inclusion of XBMs in upstream u8g2 library, it's required to provide precompiled binary files. This can be performed online with [Online-Utility's Image Converter](http://www.online-utility.org/image_converter.jsp): Convert from XBM to MONO format and upload the binary result.
+
+## u8g2.disp:getAscent()
+Returns the reference height of the glyphs above the baseline (ascent).
+
+See [u8g2 getAscent()](https://github.com/olikraus/u8g2/wiki/u8g2reference#getascent).
+
+## u8g2.disp:getDescent()
+Returns the reference height of the glyphs below the baseline (descent).
+
+See [u8g2 getDescent()](https://github.com/olikraus/u8g2/wiki/u8g2reference#getdescent).
+
+## u8g2.disp:getStrWidth()
+Return the pixel width of string.
+
+See [u8g2 getStrWidth()](https://github.com/olikraus/u8g2/wiki/u8g2reference#getstrwidth).
+
+## u8g2.disp:getUTF8Width()
+Return the pixel width of an UTF-8 encoded string.
+
+See [u8g2 getUTF8Width()](https://github.com/olikraus/u8g2/wiki/u8g2reference#getutf8width).
+
+## u8g2.disp:sendBuffer()
+Send the content of the memory frame buffer to the display.
+
+See [u8g2 sendBuffer()](https://github.com/olikraus/u8g2/wiki/u8g2reference#sendbuffer).
+
+## u8g2.disp:setBitmapMode()
+Define bitmap background color mode.
+
+See [u8g2 setBitmapMode()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setbitmapmode).
+
+## u8g2.disp:setContrast()
+Set the contrast or brightness.
+
+See [u8g2 setContrast()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setconstrast).
+
+## u8g2.disp:setDisplayRotation()
+Changes the display rotation.
+
+See [u8g2 setDisplayRotation()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setdisplayrotation).
+
+## u8g2.disp:setDrawColor()
+Defines the bit value (color index) for all drawing functions.
+
+See [u8g2 setDrawColor()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setdrawcolor).
+
+## u8g2.disp:setFlipMode()
+Set flip (180 degree rotation) mode.
+
+See [u8g2 setFlipMode()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setflipmode).
+
+## u8g2.disp:setFont()
+Define a u8g2 font for the glyph and string drawing functions. They can be supplied as strings or compiled into the firmware image. They are available as `u8g2.<font_name>` in Lua.
+
+See [u8g2 setFont()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfont).
+
+## u8g2.disp:setFontDirection()
+Set the drawing direction of all strings or glyphs.
+
+See [u8g2 setFontDirection()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontdirection).
+
+## u8g2.disp:setFontMode()
+Define font background color mode.
+
+See [u8g2 setFontMode()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontmode).
+
+## u8g2.disp:setFontPosBaseline()
+Change the reference position for the glyph and string draw functions to "baseline".
+
+See [u8g2 setFontPosBaseline()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontposbaseline).
+
+## u8g2.disp:setFontPosBottom()
+Change the reference position for the glyph and string draw functions to "bottom".
+
+See [u8g2 setFontPosBottom()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontposbottom).
+
+## u8g2.disp:setFontPosTop()
+Change the reference position for the glyph and string draw functions to "top".
+
+See [u8g2 setFontPosTop()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontpostop).
+
+## u8g2.disp:setFontPosCenter()
+Change the reference position for the glyph and string draw functions to "center".
+
+See [u8g2 setFontPosCenter()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontposcenter).
+
+## u8g2.disp:setFontRefHeightAll()
+Set ascent and descent calculation mode to "highest and lowest glyph".
+
+See [u8g2 setFontRefHeightAll()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontrefheightall).
+
+## u8g2.disp:setFontRefHeightExtendedText()
+Set ascent and descent calculation mode to "highest of [A1(], lowest of [g(]".
+
+See [u8g2 setFontRefHeightExtendedText()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontrefheightextendedtext).
+
+## u8g2.disp:setFontRefHeightText()
+Set ascent and descent calculation mode to "highest of [A1], lowest of [g]".
+
+See [u8g2 setFontRefHeightText()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setfontrefheighttext).
+
+## u8g2.disp:setPowerSave()
+Activate or disable power save mode of the display.
+
+See [u8g2 setPowerSave()](https://github.com/olikraus/u8g2/wiki/u8g2reference#setpowersave).

+ 260 - 0
lua_examples/u8g2/graphics_test.lua

@@ -0,0 +1,260 @@
+-- ***************************************************************************
+-- Graphics Test
+--
+-- This script executes several features of u8g2 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 id  = i2c.HW0
+  local sda = 16
+  local scl = 17
+  local sla = 0x3c
+  i2c.setup(id, sda, scl, i2c.FAST)
+  disp = u8g2.ssd1306_i2c_128x64_noname(id, sla)
+end
+
+-- setup SPI and connect display
+function init_spi_display()
+  -- pins can be assigned freely to available GPIOs
+  local sclk = 19
+  local mosi = 23
+  local cs   = 22
+  local dc   = 16
+  local res  = 17
+
+  local bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
+
+  disp = u8g2.ssd1306_128x64_noname(bus, 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()

+ 0 - 115
lua_examples/u8glib/u8g_bitmaps.lua

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

+ 0 - 73
lua_examples/u8glib/u8g_drawloop.lua

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

+ 0 - 177
lua_examples/u8glib/u8g_graphics_test.lua

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

BIN
lua_examples/u8glib/u8g_rook.bm


+ 0 - 97
lua_examples/u8glib/u8g_rotation.lua

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

BIN
lua_examples/u8glib/u8glib_logo.xbm


+ 20 - 18
mkdocs.yml

@@ -32,22 +32,24 @@ pages:
         - Extension Developer FAQ: 'en/extn-developer-faq.md'
     - Support: 'en/support.md'
     - Modules:
-        - 'adc':         'en/modules/adc.md'
-        - 'bit':         'en/modules/bit.md'
-        - 'bthci':       'en/modules/bthci.md'
-        - 'can':         'en/modules/can.md'
-        - 'dht':         'en/modules/dht.md'
-        - 'file':        'en/modules/file.md'
-        - 'gpio':        'en/modules/gpio.md'
-        - 'i2c':         'en/modules/i2c.md'
-        - 'node':        'en/modules/node.md'
-        - 'ow (1-Wire)': 'en/modules/ow.md'
-        - 'sdmmc':       'en/modules/sdmmc.md'
-        - 'sigma delta': 'en/modules/sigma-delta.md'
-        - 'spi':         'en/modules/spi.md'
-        - 'struct':      'en/modules/struct.md'
-        - 'tmr':         'en/modules/tmr.md'
-        - 'uart':        'en/modules/uart.md'
-        - 'wifi':        'en/modules/wifi.md'
-        - 'ws2812':      'en/modules/ws2812.md'
+        - 'adc':          'en/modules/adc.md'
+        - 'bit':          'en/modules/bit.md'
+        - 'bthci':        'en/modules/bthci.md'
+        - 'can':          'en/modules/can.md'
+        - 'dht':          'en/modules/dht.md'
+        - 'file':         'en/modules/file.md'
+        - 'gpio':         'en/modules/gpio.md'
+        - 'i2c':          'en/modules/i2c.md'
+        - 'node':         'en/modules/node.md'
+        - 'ow (1-Wire)':  'en/modules/ow.md'
+        - 'sdmmc':        'en/modules/sdmmc.md'
+        - 'sigma delta':  'en/modules/sigma-delta.md'
+        - 'spi':          'en/modules/spi.md'
+        - 'struct':       'en/modules/struct.md'
+        - 'tmr':          'en/modules/tmr.md'
+        - 'u8g2':         'en/modules/u8g2.md'
+        - 'u8g2 Display': 'en/modules/u8g2_disp.md'
+        - 'uart':         'en/modules/uart.md'
+        - 'wifi':         'en/modules/wifi.md'
+        - 'ws2812':       'en/modules/ws2812.md'
 

+ 42 - 0
tools/u8g2_config_displays.pl

@@ -0,0 +1,42 @@
+#!/usr/bin/perl -w
+
+my (@i2c_displays, @spi_displays);
+
+# scan provided header file for CONFIG_U8G2_I2C and CONFIG_U8G2_SPI entries
+while (<STDIN>) {
+    if (/^\s*#\s*define\s+CONFIG_U8G2_I2C_([^_]+)_(\S+)\s+1/) {
+        push(@i2c_displays, lc($1)."_i2c_".lc($2));
+    }
+    if (/^\s*#\s*define\s+CONFIG_U8G2_SPI_(\S+)\s+1/) {
+        push(@spi_displays, lc($1));
+    }
+}
+
+
+if (@i2c_displays > 0 || @spi_displays > 0) {
+    print << 'HEADER';
+
+#ifndef _U8G2_DISPLAYS_H
+#define _U8G2_DISPLAYS_H
+
+#define U8G2_DISPLAY_TABLE_ENTRY(function, binding)
+
+HEADER
+
+    print("#define U8G2_DISPLAY_TABLE_I2C \\\n");
+    foreach my $display (@i2c_displays) {
+        print("  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_${display}_f, $display) \\\n");
+    }
+    print("\n");
+
+    print("#define U8G2_DISPLAY_TABLE_SPI \\\n");
+    foreach my $display (@spi_displays) {
+        print("  U8G2_DISPLAY_TABLE_ENTRY(u8g2_Setup_${display}_f, $display) \\\n");
+    }
+    print("\n");
+
+    print << 'FOOTER';
+
+#endif /* _U8G2_DISPLAYS_H */
+FOOTER
+}

+ 33 - 0
tools/u8g2_config_fonts.pl

@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+
+my @font_selection;
+
+# scan provided header file for CONFIG_U8G2_FONT_SELECTION entry
+while (<STDIN>) {
+    if (/^\s*#\s*define\s+CONFIG_U8G2_FONT_SELECTION\s+"([^"]+)"/) {
+        @font_selection = split(/,/, $1);
+        last;
+    }
+}
+
+if (@font_selection > 0) {
+    print << 'HEADER';
+
+#ifndef _U8G2_FONTS_H
+#define _U8G2_FONTS_H
+
+#define U8G2_FONT_TABLE_ENTRY(font)
+
+#define U8G2_FONT_TABLE \
+HEADER
+
+    foreach my $font (@font_selection) {
+        print("  U8G2_FONT_TABLE_ENTRY($font) \\\n");
+    }
+
+    print << 'FOOTER';
+
+
+#endif /* _U8G2_FONTS_H */
+FOOTER
+}