Add u8g2 module.

This commit is contained in:
devsaurus 2017-05-26 21:39:29 +02:00
parent 329bd73b63
commit a8ff8f059d
24 changed files with 2177 additions and 484 deletions

3
.gitmodules vendored
View File

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

View File

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

View File

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

View File

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

View File

@ -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
components/modules/u8g2.c Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

1
components/u8g2/u8g2 Submodule

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

View File

@ -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
docs/en/modules/u8g2.md Normal file
View File

@ -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`, ...

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

View File

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

Binary file not shown.

View File

@ -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
tools/u8g2_config_displays.pl Executable file
View File

@ -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
tools/u8g2_config_fonts.pl Executable file
View File

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