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
|
||||
@mkdir -p $(OBJODIR);
|
||||
@mkdir -p $(dir $@);
|
||||
$(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o $@ -c $<
|
||||
|
||||
$(OBJODIR)/%.d: %.c
|
||||
@mkdir -p $(OBJODIR);
|
||||
@mkdir -p $(dir $@);
|
||||
@echo DEPEND: $(CC) -M $(CFLAGS) $<
|
||||
@set -e; rm -f $@; \
|
||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||
|
@ -331,22 +331,22 @@ $(OBJODIR)/%.d: %.cpp
|
|||
rm -f $@.$$$$
|
||||
|
||||
$(OBJODIR)/%.o: %.s
|
||||
@mkdir -p $(OBJODIR);
|
||||
@mkdir -p $(dir $@);
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(OBJODIR)/%.d: %.s
|
||||
@mkdir -p $(OBJODIR); \
|
||||
@mkdir -p $(dir $@); \
|
||||
set -e; rm -f $@; \
|
||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
|
||||
rm -f $@.$$$$
|
||||
|
||||
$(OBJODIR)/%.o: %.S
|
||||
@mkdir -p $(OBJODIR);
|
||||
@mkdir -p $(dir $@);
|
||||
$(CC) $(CFLAGS) -D__ASSEMBLER__ -o $@ -c $<
|
||||
|
||||
$(OBJODIR)/%.d: %.S
|
||||
@mkdir -p $(OBJODIR); \
|
||||
@mkdir -p $(dir $@); \
|
||||
set -e; rm -f $@; \
|
||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||
sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 $@ : ,g' < $@.$$$$ > $@; \
|
||||
|
|
|
@ -38,6 +38,7 @@ SUBDIRS= \
|
|||
lua \
|
||||
lwip \
|
||||
task \
|
||||
u8g2lib \
|
||||
smart \
|
||||
modules \
|
||||
spiffs \
|
||||
|
@ -68,6 +69,7 @@ COMPONENTS_eagle.app.v6 = \
|
|||
libc/liblibc.a \
|
||||
lua/liblua.a \
|
||||
lwip/liblwip.a \
|
||||
u8g2lib/u8g2lib.a \
|
||||
smart/smart.a \
|
||||
spiffs/spiffs.a \
|
||||
fatfs/libfatfs.a \
|
||||
|
|
|
@ -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_TSL2561
|
||||
#define LUA_USE_MODULES_UART
|
||||
//#define LUA_USE_MODULES_U8G2
|
||||
//#define LUA_USE_MODULES_UCG
|
||||
//#define LUA_USE_MODULES_WEBSOCKET
|
||||
#define LUA_USE_MODULES_WIFI
|
||||
|
|
|
@ -43,6 +43,7 @@ INCLUDES += -I ./
|
|||
INCLUDES += -I ../libc
|
||||
INCLUDES += -I ../coap
|
||||
INCLUDES += -I ../mqtt
|
||||
INCLUDES += -I ../u8g2lib/u8g2/src/clib
|
||||
INCLUDES += -I ../ucglib
|
||||
INCLUDES += -I ../lua
|
||||
INCLUDES += -I ../pcm
|
||||
|
|
|
@ -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 ../libc
|
||||
INCLUDES += -I ../lua
|
||||
INCLUDES += -I ../u8g2lib/u8g2/src/clib
|
||||
PDIR := ../$(PDIR)
|
||||
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