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