Add ucg module.

This commit is contained in:
devsaurus 2018-10-04 23:01:34 +02:00
parent c1de414ba1
commit 45c63a8236
17 changed files with 1519 additions and 39 deletions

3
.gitmodules vendored
View File

@ -11,3 +11,6 @@
[submodule "components/espmqtt"]
path = components/espmqtt
url = https://github.com/tuanpmt/espmqtt
[submodule "components/ucg/ucg"]
path = components/ucg/ucg
url = https://github.com/olikraus/Ucglib_Arduino.git

View File

@ -175,6 +175,15 @@ config LUA_MODULE_U8G2
source "$PROJECT_PATH/components/u8g2/u8g2.kconfig"
config LUA_MODULE_UCG
bool "UCG module"
default "n"
select LUA_MODULE_SPI
help
Includes the ucg module.
source "$PROJECT_PATH/components/ucg/ucg.kconfig"
config LUA_MODULE_WIFI
bool "WiFi module"
default "y"

View File

@ -22,7 +22,7 @@ CFLAGS += \
-Werror=unused-but-set-variable \
-Werror=unused-variable \
COMPONENT_EXTRA_CLEAN := u8g2_fonts.h u8g2_displays.h
COMPONENT_EXTRA_CLEAN := u8g2_fonts.h u8g2_displays.h ucg_config.h
u8g2.o: u8g2_fonts.h u8g2_displays.h
@ -31,3 +31,8 @@ u8g2_fonts.h: $(BUILD_DIR_BASE)/include/sdkconfig.h
u8g2_displays.h: $(BUILD_DIR_BASE)/include/sdkconfig.h
perl -w $(PROJECT_PATH)/tools/u8g2_config_displays.pl < $^ > $@
ucg.o: ucg_config.h
ucg_config.h: $(BUILD_DIR_BASE)/include/sdkconfig.h
perl -w $(PROJECT_PATH)/tools/ucg_config.pl < $^ > $@

770
components/modules/ucg.c Normal file
View File

@ -0,0 +1,770 @@
// Module for Ucglib
#include "module.h"
#include "lauxlib.h"
#define USE_PIN_LIST
#include "ucg.h"
#include "ucg_nodemcu_hal.h"
#include "ucg_config.h"
#ifdef ESP_PLATFORM
// ESP32
#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
{
ucg_nodemcu_t ucg;
ucg_dev_fnptr dev_cb;
ucg_dev_fnptr ext_cb;
// For Print() function
ucg_int_t tx, ty;
uint8_t tdir;
int font_ref;
int host_ref;
} ucg_ud_t;
// shorthand macro for the ucg structure inside the userdata
#define GET_UCG() \
ucg_ud_t *ud = (ucg_ud_t *)luaL_checkudata( L, 1, "ucg.display" ); \
ucg_t *ucg = (ucg_t *)(&(ud->ucg));
// helper function: retrieve given number of integer arguments
static void lucg_get_int_args( lua_State *L, uint8_t stack, uint8_t num, ucg_int_t *args)
{
while (num-- > 0) {
*args++ = luaL_checkinteger( L, stack++ );
}
}
// Lua: ucg.begin( self, fontmode )
static int lucg_begin( lua_State *L )
{
GET_UCG();
ucg_Init( ucg, ud->dev_cb, ud->ext_cb, ucg_com_nodemcu_hw_spi );
ucg_int_t fontmode = luaL_checkinteger( L, 2 );
ucg_SetFontMode( ucg, fontmode );
return 0;
}
// Lua: ucg.clearScreen( self )
static int lucg_clearScreen( lua_State *L )
{
GET_UCG();
ucg_ClearScreen( ucg );
return 0;
}
// Lua: ucg.draw90Line( self, x, y, len, dir, col_idx )
static int lucg_draw90Line( lua_State *L )
{
GET_UCG();
ucg_int_t args[5];
lucg_get_int_args( L, 2, 5, args );
ucg_Draw90Line( ucg, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
// Lua: ucg.drawBox( self, x, y, w, h )
static int lucg_drawBox( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawBox( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawCircle( self, x0, y0, rad, option )
static int lucg_drawCircle( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawCircle( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawDisc( self, x0, y0, rad, option )
static int lucg_drawDisc( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawDisc( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawFrame( self, x, y, w, h )
static int lucg_drawFrame( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawFrame( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawGradientBox( self, x, y, w, h )
static int lucg_drawGradientBox( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawGradientBox( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: width = ucg.drawGlyph( self, x, y, dir, encoding )
static int lucg_drawGlyph( lua_State *L )
{
GET_UCG();
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
const char *c = luaL_checkstring( L, (1+3) + 1 );
if (c == NULL)
return 0;
lua_pushinteger( L, ucg_DrawGlyph( ucg, args[0], args[1], args[2], *c ) );
return 1;
}
// Lua: ucg.drawGradientLine( self, x, y, len, dir )
static int lucg_drawGradientLine( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawGradientLine( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawHLine( self, x, y, len )
static int lucg_drawHLine( lua_State *L )
{
GET_UCG();
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
ucg_DrawHLine( ucg, args[0], args[1], args[2] );
return 0;
}
// Lua: ucg.drawLine( self, x1, y1, x2, y2 )
static int lucg_drawLine( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_DrawLine( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.drawPixel( self, x, y )
static int lucg_drawPixel( lua_State *L )
{
GET_UCG();
ucg_int_t args[2];
lucg_get_int_args( L, 2, 2, args );
ucg_DrawPixel( ucg, args[0], args[1] );
return 0;
}
// Lua: ucg.drawRBox( self, x, y, w, h, r )
static int lucg_drawRBox( lua_State *L )
{
GET_UCG();
ucg_int_t args[5];
lucg_get_int_args( L, 2, 5, args );
ucg_DrawRBox( ucg, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
// Lua: ucg.drawRFrame( self, x, y, w, h, r )
static int lucg_drawRFrame( lua_State *L )
{
GET_UCG();
ucg_int_t args[5];
lucg_get_int_args( L, 2, 5, args );
ucg_DrawRFrame( ucg, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
// Lua: width = ucg.drawString( self, x, y, dir, str )
static int lucg_drawString( lua_State *L )
{
GET_UCG();
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
const char *s = luaL_checkstring( L, (1+3) + 1 );
if (s == NULL)
return 0;
lua_pushinteger( L, ucg_DrawString( ucg, args[0], args[1], args[2], s ) );
return 1;
}
// Lua: ucg.drawTetragon( self, x0, y0, x1, y1, x2, y2, x3, y3 )
static int lucg_drawTetragon( lua_State *L )
{
GET_UCG();
ucg_int_t args[8];
lucg_get_int_args( L, 2, 8, args );
ucg_DrawTetragon( ucg, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7] );
return 0;
}
// Lua: ucg.drawTriangle( self, x0, y0, x1, y1, x2, y2 )
static int lucg_drawTriangle( lua_State *L )
{
GET_UCG();
ucg_int_t args[6];
lucg_get_int_args( L, 2, 6, args );
ucg_DrawTriangle( ucg, args[0], args[1], args[2], args[3], args[4], args[5] );
return 0;
}
// Lua: ucg.drawVLine( self, x, y, len )
static int lucg_drawVLine( lua_State *L )
{
GET_UCG();
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
ucg_DrawVLine( ucg, args[0], args[1], args[2] );
return 0;
}
// Lua: height = ucg.getFontAscent( self )
static int lucg_getFontAscent( lua_State *L )
{
GET_UCG();
lua_pushinteger( L, ucg_GetFontAscent( ucg ) );
return 1;
}
// Lua: height = ucg.getFontDescent( self )
static int lucg_getFontDescent( lua_State *L )
{
GET_UCG();
lua_pushinteger( L, ucg_GetFontDescent( ucg ) );
return 1;
}
// Lua: height = ucg.getHeight( self )
static int lucg_getHeight( lua_State *L )
{
GET_UCG();
lua_pushinteger( L, ucg_GetHeight( ucg ) );
return 1;
}
// Lua: width = ucg.getStrWidth( self, string )
static int lucg_getStrWidth( lua_State *L )
{
GET_UCG();
const char *s = luaL_checkstring( L, 2 );
if (s == NULL)
return 0;
lua_pushinteger( L, ucg_GetStrWidth( ucg, s ) );
return 1;
}
// Lua: width = ucg.getWidth( self )
static int lucg_getWidth( lua_State *L )
{
GET_UCG();
lua_pushinteger( L, ucg_GetWidth( ucg ) );
return 1;
}
// Lua: ucg.setClipRange( self, x, y, w, h )
static int lucg_setClipRange( lua_State *L )
{
GET_UCG();
ucg_int_t args[4];
lucg_get_int_args( L, 2, 4, args );
ucg_SetClipRange( ucg, args[0], args[1], args[2], args[3] );
return 0;
}
// Lua: ucg.setColor( self, [idx], r, g, b )
static int lucg_setColor( lua_State *L )
{
GET_UCG();
ucg_int_t args[3];
lucg_get_int_args( L, 2, 3, args );
ucg_int_t opt = luaL_optint( L, (1+3) + 1, -1 );
if (opt < 0) {
ucg_SetColor( ucg, 0, args[0], args[1], args[2] );
} else {
ucg_SetColor( ucg, args[0], args[1], args[2], opt );
}
return 0;
}
// Lua: ucg.setFont( self, font )
static int lucg_setFont( lua_State *L )
{
GET_UCG();
ucg_fntpgm_uint8_t *font = (ucg_fntpgm_uint8_t *)lua_touserdata( L, 2 );
if (font != NULL)
ucg_SetFont( ucg, font );
else
luaL_argerror(L, 2, "font data expected");
return 0;
}
// Lua: ucg.print( self, str )
static int lucg_print( lua_State *L )
{
GET_UCG();
const char *s = luaL_checkstring( L, 2 );
if (s == NULL)
return 0;
while (*s)
{
ucg_int_t delta;
delta = ucg_DrawGlyph(ucg, ud->tx, ud->ty, ud->tdir, *(s++));
switch(ud->tdir) {
case 0: ud->tx += delta; break;
case 1: ud->ty += delta; break;
case 2: ud->tx -= delta; break;
default: case 3: ud->ty -= delta; break;
}
}
return 0;
}
// Lua: ucg.setFontMode( self, fontmode )
static int lucg_setFontMode( lua_State *L )
{
GET_UCG();
ucg_int_t fontmode = luaL_checkinteger( L, 2 );
ucg_SetFontMode( ucg, fontmode );
return 0;
}
// Lua: ucg.setFontPosBaseline( self )
static int lucg_setFontPosBaseline( lua_State *L )
{
GET_UCG();
ucg_SetFontPosBaseline( ucg );
return 0;
}
// Lua: ucg.setFontPosBottom( self )
static int lucg_setFontPosBottom( lua_State *L )
{
GET_UCG();
ucg_SetFontPosBottom( ucg );
return 0;
}
// Lua: ucg.setFontPosCenter( self )
static int lucg_setFontPosCenter( lua_State *L )
{
GET_UCG();
ucg_SetFontPosCenter( ucg );
return 0;
}
// Lua: ucg.setFontPosTop( self )
static int lucg_setFontPosTop( lua_State *L )
{
GET_UCG();
ucg_SetFontPosTop( ucg );
return 0;
}
// Lua: ucg.setMaxClipRange( self )
static int lucg_setMaxClipRange( lua_State *L )
{
GET_UCG();
ucg_SetMaxClipRange( ucg );
return 0;
}
// Lua: ucg.setPrintPos( self, x, y )
static int lucg_setPrintPos( lua_State *L )
{
GET_UCG();
(void)ucg;
ucg_int_t args[2];
lucg_get_int_args( L, 2, 2, args );
ud->tx = args[0];
ud->ty = args[1];
return 0;
}
// Lua: ucg.setPrintDir( self, dir )
static int lucg_setPrintDir( lua_State *L )
{
GET_UCG();
(void)ucg;
ud->tdir = luaL_checkinteger( L, 2 );
return 0;
}
// Lua: ucg.setRotate90( self )
static int lucg_setRotate90( lua_State *L )
{
GET_UCG();
ucg_SetRotate90( ucg );
return 0;
}
// Lua: ucg.setRotate180( self )
static int lucg_setRotate180( lua_State *L )
{
GET_UCG();
ucg_SetRotate180( ucg );
return 0;
}
// Lua: ucg.setRotate270( self )
static int lucg_setRotate270( lua_State *L )
{
GET_UCG();
ucg_SetRotate270( ucg );
return 0;
}
// Lua: ucg.setScale2x2( self )
static int lucg_setScale2x2( lua_State *L )
{
GET_UCG();
ucg_SetScale2x2( ucg );
return 0;
}
// Lua: ucg.undoRotate( self )
static int lucg_undoRotate( lua_State *L )
{
GET_UCG();
ucg_UndoRotate( ucg );
return 0;
}
// Lua: ucg.undoScale( self )
static int lucg_undoScale( lua_State *L )
{
GET_UCG();
ucg_UndoScale( ucg );
return 0;
}
// device destructor
static int lucg_close_display( lua_State *L )
{
return 0;
}
// ***************************************************************************
// Device constructors
//
//
static int ldisplay_hw_spi( lua_State *L, ucg_dev_fnptr device, ucg_dev_fnptr extension )
{
int stack = 0;
#ifndef ESP_PLATFORM
// ESP8266
typedef struct {
int host;
} lspi_host_t;
lspi_host_t host_elem;
lspi_host_t *host = &host_elem;
#else
// ESP32
lspi_host_t *host = NULL;
#endif
int host_ref = LUA_NOREF;
int cs = -1;
int dc = -1;
int res = -1;
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 = 1;
} else if (lua_type( L, stack ) == LUA_TNUMBER) {
host->host = luaL_checkint( L, stack );
get_spi_pins = 1;
} else {
get_spi_pins = 0;
stack--;
}
if (get_spi_pins) {
cs = luaL_checkint( L, ++stack );
dc = luaL_checkint( L, ++stack );
res = luaL_optint( L, ++stack, -1 );
}
ucg_ud_t *ud = (ucg_ud_t *) lua_newuserdata( L, sizeof( ucg_ud_t ) );
ucg_nodemcu_t *ext_ucg = &(ud->ucg);
ud->font_ref = LUA_NOREF;
ud->host_ref = host_ref;
ext_ucg->hal = host ? (void *)(host->host) : NULL;
ucg_t *ucg = (ucg_t *)ext_ucg;
/* do a dummy init so that something usefull is part of the ucg structure */
ucg_Init( ucg, ucg_dev_default_cb, ucg_ext_none, (ucg_com_fnptr)0 );
/* reset cursor position */
ud->tx = 0;
ud->ty = 0;
ud->tdir = 0; /* default direction */
uint8_t i;
for( i = 0; i < UCG_PIN_COUNT; i++ )
ucg->pin_list[i] = UCG_PIN_VAL_NONE;
ud->dev_cb = device;
ud->ext_cb = extension;
if (res >= 0)
ucg->pin_list[UCG_PIN_RST] = res;
ucg->pin_list[UCG_PIN_CD] = dc;
ucg->pin_list[UCG_PIN_CS] = cs;
/* set its metatable */
luaL_getmetatable(L, "ucg.display");
lua_setmetatable(L, -2);
return 1;
}
#undef UCG_DISPLAY_TABLE_ENTRY
#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension) \
static int l ## binding( lua_State *L ) \
{ \
return ldisplay_hw_spi( L, device, extension ); \
}
//
// Unroll the display table and insert binding functions.
UCG_DISPLAY_TABLE
//
// ***************************************************************************
// Module function map
static const LUA_REG_TYPE lucg_display_map[] =
{
{ LSTRKEY( "begin" ), LFUNCVAL( lucg_begin ) },
{ LSTRKEY( "clearScreen" ), LFUNCVAL( lucg_clearScreen ) },
{ LSTRKEY( "draw90Line" ), LFUNCVAL( lucg_draw90Line ) },
{ LSTRKEY( "drawBox" ), LFUNCVAL( lucg_drawBox ) },
{ LSTRKEY( "drawCircle" ), LFUNCVAL( lucg_drawCircle ) },
{ LSTRKEY( "drawDisc" ), LFUNCVAL( lucg_drawDisc ) },
{ LSTRKEY( "drawFrame" ), LFUNCVAL( lucg_drawFrame ) },
{ LSTRKEY( "drawGlyph" ), LFUNCVAL( lucg_drawGlyph ) },
{ LSTRKEY( "drawGradientBox" ), LFUNCVAL( lucg_drawGradientBox ) },
{ LSTRKEY( "drawGradientLine" ), LFUNCVAL( lucg_drawGradientLine ) },
{ LSTRKEY( "drawHLine" ), LFUNCVAL( lucg_drawHLine ) },
{ LSTRKEY( "drawLine" ), LFUNCVAL( lucg_drawLine ) },
{ LSTRKEY( "drawPixel" ), LFUNCVAL( lucg_drawPixel ) },
{ LSTRKEY( "drawRBox" ), LFUNCVAL( lucg_drawRBox ) },
{ LSTRKEY( "drawRFrame" ), LFUNCVAL( lucg_drawRFrame ) },
{ LSTRKEY( "drawString" ), LFUNCVAL( lucg_drawString ) },
{ LSTRKEY( "drawTetragon" ), LFUNCVAL( lucg_drawTetragon ) },
{ LSTRKEY( "drawTriangle" ), LFUNCVAL( lucg_drawTriangle ) },
{ LSTRKEY( "drawVLine" ), LFUNCVAL( lucg_drawVLine ) },
{ LSTRKEY( "getFontAscent" ), LFUNCVAL( lucg_getFontAscent ) },
{ LSTRKEY( "getFontDescent" ), LFUNCVAL( lucg_getFontDescent ) },
{ LSTRKEY( "getHeight" ), LFUNCVAL( lucg_getHeight ) },
{ LSTRKEY( "getStrWidth" ), LFUNCVAL( lucg_getStrWidth ) },
{ LSTRKEY( "getWidth" ), LFUNCVAL( lucg_getWidth ) },
{ LSTRKEY( "print" ), LFUNCVAL( lucg_print ) },
{ LSTRKEY( "setClipRange" ), LFUNCVAL( lucg_setClipRange ) },
{ LSTRKEY( "setColor" ), LFUNCVAL( lucg_setColor ) },
{ LSTRKEY( "setFont" ), LFUNCVAL( lucg_setFont ) },
{ LSTRKEY( "setFontMode" ), LFUNCVAL( lucg_setFontMode ) },
{ LSTRKEY( "setFontPosBaseline" ), LFUNCVAL( lucg_setFontPosBaseline ) },
{ LSTRKEY( "setFontPosBottom" ), LFUNCVAL( lucg_setFontPosBottom ) },
{ LSTRKEY( "setFontPosCenter" ), LFUNCVAL( lucg_setFontPosCenter ) },
{ LSTRKEY( "setFontPosTop" ), LFUNCVAL( lucg_setFontPosTop ) },
{ LSTRKEY( "setMaxClipRange" ), LFUNCVAL( lucg_setMaxClipRange ) },
{ LSTRKEY( "setPrintDir" ), LFUNCVAL( lucg_setPrintDir ) },
{ LSTRKEY( "setPrintPos" ), LFUNCVAL( lucg_setPrintPos ) },
{ LSTRKEY( "setRotate90" ), LFUNCVAL( lucg_setRotate90 ) },
{ LSTRKEY( "setRotate180" ), LFUNCVAL( lucg_setRotate180 ) },
{ LSTRKEY( "setRotate270" ), LFUNCVAL( lucg_setRotate270 ) },
{ LSTRKEY( "setScale2x2" ), LFUNCVAL( lucg_setScale2x2 ) },
{ LSTRKEY( "undoClipRange" ), LFUNCVAL( lucg_setMaxClipRange ) },
{ LSTRKEY( "undoRotate" ), LFUNCVAL( lucg_undoRotate ) },
{ LSTRKEY( "undoScale" ), LFUNCVAL( lucg_undoScale ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( lucg_close_display ) },
{ LSTRKEY( "__index" ), LROVAL ( lucg_display_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE lucg_map[] =
{
#undef UCG_DISPLAY_TABLE_ENTRY
#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension) { LSTRKEY( #binding ), LFUNCVAL ( l ## binding ) },
UCG_DISPLAY_TABLE
// Register fonts
#undef UCG_FONT_TABLE_ENTRY
#define UCG_FONT_TABLE_ENTRY(font) { LSTRKEY( #font ), LUDATA( (void *)(ucg_ ## font) ) },
UCG_FONT_TABLE
// Font modes
{ LSTRKEY( "FONT_MODE_TRANSPARENT" ), LNUMVAL( UCG_FONT_MODE_TRANSPARENT ) },
{ LSTRKEY( "FONT_MODE_SOLID" ), LNUMVAL( UCG_FONT_MODE_SOLID ) },
// Options for circle/ disc drawing
{ LSTRKEY( "DRAW_UPPER_RIGHT" ), LNUMVAL( UCG_DRAW_UPPER_RIGHT ) },
{ LSTRKEY( "DRAW_UPPER_LEFT" ), LNUMVAL( UCG_DRAW_UPPER_LEFT ) },
{ LSTRKEY( "DRAW_LOWER_RIGHT" ), LNUMVAL( UCG_DRAW_LOWER_RIGHT ) },
{ LSTRKEY( "DRAW_LOWER_LEFT" ), LNUMVAL( UCG_DRAW_LOWER_LEFT ) },
{ LSTRKEY( "DRAW_ALL" ), LNUMVAL( UCG_DRAW_ALL ) },
{ LSTRKEY( "__metatable" ), LROVAL( lucg_map ) },
{ LNILKEY, LNILVAL }
};
int luaopen_ucg( lua_State *L )
{
luaL_rometatable(L, "ucg.display", (void *)lucg_display_map); // create metatable
return 0;
}
NODEMCU_MODULE(UCG, "ucg", lucg_map, luaopen_ucg);

View File

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

View File

@ -0,0 +1,17 @@
#ifndef _UCG_NODEMCU_HAL_H
#define _UCG_NODEMCU_HAL_H
#include "ucg.h"
// extend standard ucg_t struct with info that's needed in the communication callbacks
typedef struct {
ucg_t ucg;
void *hal;
} ucg_nodemcu_t;
int16_t ucg_com_nodemcu_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data);
#endif /* _UCG_NODEMCU_HAL_H */

View File

@ -0,0 +1,215 @@
#include <string.h>
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "platform.h"
#include "ucg_nodemcu_hal.h"
// static variables containing info about the spi link
// TODO: move to user space once available
typedef struct {
uint8_t host;
spi_device_handle_t device;
uint8_t last_dc;
} hal_spi_t;
// transfers with payload smaller than this should be done in
// polling mode to save overhead
#define SPI_TRANSFER_POLLING_TRESHOLD 16
static void send_byte( hal_spi_t *hal, uint8_t data ) {
spi_transaction_t trans;
memset( &trans, 0, sizeof( trans ) );
trans.flags = SPI_TRANS_USE_TXDATA;
trans.length = 8;
trans.tx_data[0] = data;
spi_device_polling_transmit( hal->device, &trans );
}
// send buffer in DMA'able RAM for caching data in bigger transfers
#define SEND_BUFFER_SIZE (2*3 * 20)
static DMA_ATTR uint8_t send_buffer[SEND_BUFFER_SIZE];
int16_t ucg_com_nodemcu_hw_spi(ucg_t *ucg, int16_t msg, uint16_t arg, uint8_t *data)
{
hal_spi_t *hal = ((ucg_nodemcu_t *)ucg)->hal;
switch(msg) {
case UCG_COM_MSG_POWER_UP:
/* "data" is a pointer to ucg_com_info_t structure with the following information: */
/* ((ucg_com_info_t *)data)->serial_clk_speed value in nanoseconds */
/* ((ucg_com_info_t *)data)->parallel_clk_speed value in nanoseconds */
/* setup pins */
for (int idx = 0; idx < UCG_PIN_COUNT; idx++) {
if (ucg->pin_list[idx] != UCG_PIN_VAL_NONE) {
// configure pin as output
gpio_config_t cfg;
memset( (void *)&cfg, 0, sizeof( cfg ) );
cfg.pin_bit_mask = 1ULL << ucg->pin_list[idx];
cfg.mode = GPIO_MODE_OUTPUT;
cfg.pull_up_en = GPIO_PULLUP_DISABLE;
cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;
cfg.intr_type = GPIO_INTR_DISABLE;
gpio_config( &cfg );
}
}
{
// the hal member initially contains the spi host id
int host = (int)hal;
if (!(hal = malloc( sizeof ( hal_spi_t ) )))
return 0;
hal->host = host;
((ucg_nodemcu_t *)ucg)->hal = hal;
// set up the spi device
spi_device_interface_config_t config;
memset( &config, 0, sizeof( config ) );
config.spics_io_num = -1; // CS is controlled by ucg gpio mechanism
config.mode = 0;
config.clock_speed_hz = 10000000;
config.queue_size = 1;
spi_bus_add_device( hal->host, &config, &(hal->device) );
hal->last_dc = 0;
}
break;
case UCG_COM_MSG_POWER_DOWN:
break;
case UCG_COM_MSG_DELAY:
ets_delay_us(arg);
break;
case UCG_COM_MSG_CHANGE_RESET_LINE:
if (ucg->pin_list[UCG_PIN_RST] != UCG_PIN_VAL_NONE)
gpio_set_level( ucg->pin_list[UCG_PIN_RST], arg );
break;
case UCG_COM_MSG_CHANGE_CS_LINE:
if ( ucg->pin_list[UCG_PIN_CS] != UCG_PIN_VAL_NONE )
gpio_set_level( ucg->pin_list[UCG_PIN_CS], arg );
break;
case UCG_COM_MSG_CHANGE_CD_LINE:
gpio_set_level( ucg->pin_list[UCG_PIN_CD], arg );
break;
case UCG_COM_MSG_SEND_BYTE:
send_byte( hal, arg );
break;
case UCG_COM_MSG_REPEAT_1_BYTE:
{
spi_transaction_t trans;
memset( &trans, 0, sizeof( trans ) );
trans.tx_buffer = send_buffer;
while (arg > 0) {
size_t idx;
for (idx = 0; (idx < SEND_BUFFER_SIZE) && (arg > 0); idx++, arg--) {
send_buffer[idx] = data[0];
}
trans.length = idx * 8;
trans.rxlength = 0;
if (idx < SPI_TRANSFER_POLLING_TRESHOLD) {
spi_device_polling_transmit( hal->device, &trans );
} else {
spi_device_transmit( hal->device, &trans );
}
}
}
break;
case UCG_COM_MSG_REPEAT_2_BYTES:
{
spi_transaction_t trans;
memset( &trans, 0, sizeof( trans ) );
trans.tx_buffer = send_buffer;
while (arg > 0) {
size_t idx;
for (idx = 0; (idx < SEND_BUFFER_SIZE) && (arg > 0); idx += 2, arg--) {
send_buffer[idx] = data[0];
send_buffer[idx+1] = data[1];
}
trans.length = idx * 8;
trans.rxlength = 0;
if (idx < SPI_TRANSFER_POLLING_TRESHOLD) {
spi_device_polling_transmit( hal->device, &trans );
} else {
spi_device_transmit( hal->device, &trans );
}
}
}
break;
case UCG_COM_MSG_REPEAT_3_BYTES:
{
spi_transaction_t trans;
memset( &trans, 0, sizeof( trans ) );
trans.tx_buffer = send_buffer;
while (arg > 0) {
size_t idx;
for (idx = 0; (idx < SEND_BUFFER_SIZE) && (arg > 0); idx += 3, arg--) {
send_buffer[idx] = data[0];
send_buffer[idx+1] = data[1];
send_buffer[idx+2] = data[2];
}
trans.length = idx * 8;
trans.rxlength = 0;
if (idx < SPI_TRANSFER_POLLING_TRESHOLD) {
spi_device_polling_transmit( hal->device, &trans );
} else {
spi_device_transmit( hal->device, &trans );
}
}
}
break;
case UCG_COM_MSG_SEND_STR:
{
spi_transaction_t trans;
memset( &trans, 0, sizeof( trans ) );
trans.tx_buffer = send_buffer;
while (arg > 0) {
size_t len = arg > SEND_BUFFER_SIZE ? SEND_BUFFER_SIZE : arg;
trans.length = len * 8;
trans.rxlength = 0;
memcpy( send_buffer, data, len );
if (len < SPI_TRANSFER_POLLING_TRESHOLD) {
spi_device_polling_transmit( hal->device, &trans );
} else {
spi_device_transmit( hal->device, &trans );
}
arg -= len;
}
}
break;
case UCG_COM_MSG_SEND_CD_DATA_SEQUENCE:
while (arg > 0) {
if (*data != 0) {
/* set the data line directly, ignore the setting from UCG_CFG_CD */
if (*data == 1) {
gpio_set_level( ucg->pin_list[UCG_PIN_CD], 0 );
} else {
gpio_set_level( ucg->pin_list[UCG_PIN_CD], 1 );
}
}
data++;
send_byte( hal, *data );
data++;
arg--;
}
break;
}
return 1;
}

View File

@ -0,0 +1,3 @@
COMPONENT_SRCDIRS:=ucg/src/clib .
COMPONENT_ADD_INCLUDEDIRS:=ucg/src/clib
CPPFLAGS+=-DUSE_PIN_LIST

1
components/ucg/ucg Submodule

@ -0,0 +1 @@
Subproject commit e21641a6c1ddb0e71f7b9e01501fa739786c68b1

View File

@ -0,0 +1,66 @@
menu "Displays"
depends on LUA_MODULE_UCG
config UCG_DISPLAY_HX8352C_18X240X400
depends on LUA_MODULE_SPI
bool "hx8352c_18x240x400_hw_spi"
default "n"
config UCG_DISPLAY_ILI9163_18X128X128
depends on LUA_MODULE_SPI
bool "ili9163_18x128x128_hw_spi"
default "n"
config UCG_DISPLAY_ILI9341_18X240X320
depends on LUA_MODULE_SPI
bool "ili9341_18x240x320_hw_spi"
default "y"
config UCG_DISPLAY_ILI9486_18X320X480
depends on LUA_MODULE_SPI
bool "ili9486_18x320x480_hw_spi"
default "n"
config UCG_DISPLAY_PCF8833_16X132X132
depends on LUA_MODULE_SPI
bool "pcf8833_16x132x132_hw_spi"
default "n"
config UCG_DISPLAY_SEPS225_16X128X128_UNIVISION
depends on LUA_MODULE_SPI
bool "seps225_16x128x128_uvis_hw_spi"
default "n"
config UCG_DISPLAY_SSD1351_18X128X128_ILSOFT
depends on LUA_MODULE_SPI
bool "ssd1351_18x128x128_hw_spi"
default "n"
config UCG_DISPLAY_SSD1351_18X128X128_FT
depends on LUA_MODULE_SPI
bool "ssd1351_18x128x128_ft_hw_spi"
default "n"
config UCG_DISPLAY_SSD1331_18X96X64_UNIVISION
depends on LUA_MODULE_SPI
bool "ssd1331_18x96x64_uvis_hw_spi"
default "n"
config UCG_DISPLAY_ST7735_18X128X160
depends on LUA_MODULE_SPI
bool "st7735_18x128x160_hw_spi"
default "y"
endmenu
menu "Fonts"
depends on LUA_MODULE_UCG
config UCG_FONT_SELECTION
depends on LUA_MODULE_UCG
string "Font list"
default "font_7x13B_tr,font_helvB08_hr,font_helvB10_hr,font_helvB12_hr,font_helvB18_hr,font_ncenB24_tr,font_ncenR12_tr,font_ncenR14_hr"
help
Enter a comma-separated list of fonts.
endmenu

335
docs/en/modules/ucg.md Normal file
View File

@ -0,0 +1,335 @@
# ucg Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2015-08-05 | [Oli Kraus](https://github.com/olikraus/ucglib), [Arnim Läuger](https://github.com/devsaurus) | [Arnim Läuger](https://github.com/devsaurus) | [ucglib](../../../component/ucg/)|
Ucglib is a graphics library developed at [olikraus/ucglib](https://github.com/olikraus/ucglib) with support for color TFT displays.
!!! note "BSD License for Ucglib Code"
Universal 8bit Graphics Library (http://code.google.com/p/u8glib/)
Copyright (c) 2014, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The NodeMCU firmware supports a subset of these:
- HX8352C
- ILI9163
- ILI9341
- ILI9486
- PCF8833
- SEPS225
- SSD1331
- SSD1351
- ST7735
This integration is based on [v1.5.2](https://github.com/olikraus/Ucglib_Arduino/releases/tag/v1.5.2).
## Overview
### SPI Connection
The HSPI module is used ([more information](http://d.av.id.au/blog/esp8266-hardware-spi-hspi-general-info-and-pinout/)), so certain pins are fixed:
* HSPI CLK = GPIO14
* HSPI MOSI = GPIO13
* HSPI MISO = GPIO12 (not used)
All other pins can be assigned to any available GPIO:
* CS
* D/C
* RES (optional for some displays)
Also refer to the initialization sequence eg in [GraphicsTest.lua](https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/ucglib/GraphicsTest.lua):
```lua
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
```
### Library Usage
The Lua bindings for this library closely follow ucglib's object oriented C++ API. Based on the ucg class, you create an object for your display type.
ILI9341 via SPI:
```lua
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16, RES is optional YMMV
disp = ucg.ili9341_18x240x320_hw_spi(cs, dc, res)
```
This object provides all of ucglib's methods to control the display.
Again, refer to [GraphicsTest.lua](https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/ucglib/GraphicsTest.lua) to get an impression how this is achieved with Lua code. Visit the [ucglib homepage](https://github.com/olikraus/ucglib) for technical details.
### Display selection
HW SPI based displays with support in u8g2 can be enabled.
The procedure is different for ESP8266 and ESP32 platforms.
#### ESP8266
Add the desired entries to the display table in [app/include/ucg_config.h](../../../app/include/ucg_config.h):
```c
#define UCG_DISPLAY_TABLE \
UCG_DISPLAY_TABLE_ENTRY(ili9341_18x240x320_hw_spi, ucg_dev_ili9341_18x240x320, ucg_ext_ili9341_18) \
UCG_DISPLAY_TABLE_ENTRY(st7735_18x128x160_hw_spi, ucg_dev_st7735_18x128x160, ucg_ext_st7735_18) \
```
#### ESP32
Enable the desired entries for SPI displays in ucg's sub-menu (run `make menuconfig`).
### Fonts
ucglib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image.
The procedure is different for ESP8266 and ESP32 platforms.
#### ESP8266
Add the desired fonts to the font table in [app/include/ucg_config.h](../../../app/include/ucg_config.h):
```c
#define UCG_FONT_TABLE \
UCG_FONT_TABLE_ENTRY(font_7x13B_tr) \
UCG_FONT_TABLE_ENTRY(font_helvB12_hr) \
UCG_FONT_TABLE_ENTRY(font_helvB18_hr) \
UCG_FONT_TABLE_ENTRY(font_ncenR12_tr) \
UCG_FONT_TABLE_ENTRY(font_ncenR14_hr)
```
They will be available as `ucg.<font_name>` in Lua.
#### ESP32
Add the desired fonts to the font selection sub-entry via `make menuconfig`.
## Display Drivers
Initialize a display via Hardware SPI.
- `hx8352c_18x240x400_hw_spi()`
- `ili9163_18x128x128_hw_spi()`
- `ili9341_18x240x320_hw_spi()`
- `ili9486_18x320x480_hw_spi()`
- `pcf8833_16x132x132_hw_spi()`
- `seps225_16x128x128_uvis_hw_spi()`
- `ssd1351_18x128x128_hw_spi()`
- `ssd1351_18x128x128_ft_hw_spi()`
- `ssd1331_18x96x64_uvis_hw_spi()`
- `st7735_18x128x160_hw_spi()`
#### Syntax
`ucg.st7735_18x128x160_hw_spi(bus, cs, dc[, res])`
#### Parameters
- `bus` SPI master bus
- `cs` GPIO pin for /CS
- `dc` GPIO pin for DC
- `res` GPIO pin for /RES, none if omitted
#### Returns
ucg display object
#### Example for ESP8266
```lua
-- Hardware SPI CLK = GPIO14
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (not used)
-- Hardware SPI /CS = GPIO15 (not used)
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16, RES is optional YMMV
bus = 1
spi.setup(bus, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
-- we won't be using the HSPI /CS line, so disable it again
gpio.mode(8, gpio.INPUT, gpio.PULLUP)
disp = ucg.st7735_18x128x160_hw_spi(bus, cs, dc, res)
```
#### Example for ESP32
```lua
sclk = 19
mosi = 23
cs = 22
dc = 16
res = 17
bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
disp = ucg.st7735_18x128x160_hw_spi(bus, cs, dc, res)
```
## Constants
Constants for various functions.
`ucg.FONT_MODE_TRANSPARENT`, `ucg.FONT_MODE_SOLID`, `ucg.DRAW_UPPER_RIGHT`,
`ucg.DRAW_UPPER_LEFT`, `ucg.DRAW_LOWER_RIGHT`, `ucg.DRAW_LOWER_LEFT`, `ucg.DRAW_ALL`
`ucg.font_7x13B_tr`, ...
# ucg.disp Sub-Module
## ucg.disp:begin()
See [ucglib begin()](https://github.com/olikraus/ucglib/wiki/reference#begin).
## ucg.disp:clearScreen()
See [ucglib clearScreen()](https://github.com/olikraus/ucglib/wiki/reference#clearscreen).
## ucg.disp:draw90Line()
See [ucglib draw90Line()](https://github.com/olikraus/ucglib/wiki/reference#draw90line).
## ucg.disp:drawBox()
See [ucglib drawBox()](https://github.com/olikraus/ucglib/wiki/reference#drawbox).
## ucg.disp:drawCircle()
See [ucglib drawCircle()](https://github.com/olikraus/ucglib/wiki/reference#drawcircle).
## ucg.disp:drawDisc()
See [ucglib drawDisc()](https://github.com/olikraus/ucglib/wiki/reference#drawdisc).
## ucg.disp:drawFrame()
See [ucglib drawFrame()](https://github.com/olikraus/ucglib/wiki/reference#drawframe).
## ucg.disp:drawGlyph()
See [ucglib drawGlyph()](https://github.com/olikraus/ucglib/wiki/reference#drawglyph).
## ucg.disp:drawGradientBox()
See [ucglib drawGradientBox()](https://github.com/olikraus/ucglib/wiki/reference#drawgradientbox).
## ucg.disp:drawGradientLine()
See [ucglib drawGradientLine()](https://github.com/olikraus/ucglib/wiki/reference#drawgradientline).
## ucg.disp:drawHLine()
See [ucglib drawHLine()](https://github.com/olikraus/ucglib/wiki/reference#drawhline).
## ucg.disp:drawLine()
See [ucglib drawLine()](https://github.com/olikraus/ucglib/wiki/reference#drawline).
## ucg.disp:drawPixel()
See [ucglib drawPixel()](https://github.com/olikraus/ucglib/wiki/reference#drawpixel).
## ucg.disp:drawRBox()
See [ucglib drawRBox()](https://github.com/olikraus/ucglib/wiki/reference#drawrbox).
## ucg.disp:drawRFrame()
See [ucglib drawRFrame()](https://github.com/olikraus/ucglib/wiki/reference#drawrframe).
## ucg.disp:drawString()
See [ucglib drawString()](https://github.com/olikraus/ucglib/wiki/reference#drawstring).
## ucg.disp:drawTetragon()
See [ucglib drawTetragon()](https://github.com/olikraus/ucglib/wiki/reference#drawtetragon).
## ucg.disp:drawTriangle()
See [ucglib drawTriangle()](https://github.com/olikraus/ucglib/wiki/reference#drawrtiangle).
## ucg.disp:drawVLine()
See [ucglib drawVline()](https://github.com/olikraus/ucglib/wiki/reference#drawvline).
## ucg.disp:getFontAscent()
See [ucglib getFontAscent()](https://github.com/olikraus/ucglib/wiki/reference#getfontascent).
## ucg.disp:getFontDescent()
See [ucglib getFontDescent()](https://github.com/olikraus/ucglib/wiki/reference#getfontdescent).
## ucg.disp:getHeight()
See [ucglib getHeight()](https://github.com/olikraus/ucglib/wiki/reference#getheight).
## ucg.disp:getStrWidth()
See [ucglib getStrWidth()](https://github.com/olikraus/ucglib/wiki/reference#getstrwidth).
## ucg.disp:getWidth()
See [ucglib getWidth()](https://github.com/olikraus/ucglib/wiki/reference#getwidth).
## ucg.disp:print()
See [ucglib print()](https://github.com/olikraus/ucglib/wiki/reference#print).
## ucg.disp:setClipRange()
See [ucglib setClipRange()](https://github.com/olikraus/ucglib/wiki/reference#setcliprange).
## ucg.disp:setColor()
See [ucglib setColor()](https://github.com/olikraus/ucglib/wiki/reference#setcolor).
## ucg.disp:setFont()
Define a ucg font for the glyph and string drawing functions. They are available as `ucg.<font_name>` in Lua.
#### Syntax
`disp:setFont(font)`
#### Parameters
`font` constant to identify pre-compiled font
#### Returns
`nil`
#### Example
```lua
disp:setFont(ucg.font_7x13B_tr)
```
#### See also
[ucglib setFont()](https://github.com/olikraus/ucglib/wiki/reference#setfont)
## ucg.disp:setFontMode()
See [ucglib setFontMode()](https://github.com/olikraus/ucglib/wiki/reference#setfontmode).
## ucg.disp:setFontPosBaseline()
See [ucglib setFontPosBaseline()](https://github.com/olikraus/ucglib/wiki/reference#setfontposbaseline).
## ucg.disp:setFontPosBottom()
See [ucglib setFontPosBottom()](https://github.com/olikraus/ucglib/wiki/reference#setfontposbottom).
## ucg.disp:setFontPosCenter()
See [ucglib setFontPosCenter()](https://github.com/olikraus/ucglib/wiki/reference#setfontposcenter).
## ucg.disp:setFontPosTop()
See [ucglib setFontPosTop()](https://github.com/olikraus/ucglib/wiki/reference#setfontpostop).
## ucg.disp:setMaxClipRange()
See [ucglib setMaxClipRange()](https://github.com/olikraus/ucglib/wiki/reference#setmaxcliprange).
## ucg.disp:setPrintDir()
See [ucglib setPrintDir()](https://github.com/olikraus/ucglib/wiki/reference#setprintdir).
## ucg.disp:setPrintPos()
See [ucglib setPrintPos()](https://github.com/olikraus/ucglib/wiki/reference#setprintpos).
## ucg.disp:setRotate90()
See [ucglib setRotate90()](https://github.com/olikraus/ucglib/wiki/reference#setrotate90).
## ucg.disp:setRotate180()
See [ucglib setRotate180()](https://github.com/olikraus/ucglib/wiki/reference#setrotate180).
## ucg.disp:setRotate270()
See [ucglib setRotate270()](https://github.com/olikraus/ucglib/wiki/reference#setrotate270).
## ucg.disp:setScale2x2()
See [ucglib setScale2x2()](https://github.com/olikraus/ucglib/wiki/reference#setscale2x2).
## ucg.disp:undoClipRange()
See [ucglib undoClipRange()](https://github.com/olikraus/ucglib/wiki/reference#undocliprange).
## ucg.disp:undoRotate()
See [ucglib undoRotate()](https://github.com/olikraus/ucglib/wiki/reference#undorotate).
## ucg.disp:undoScale()
See [ucglib undoScale()](https://github.com/olikraus/ucglib/wiki/reference#undoscale).

View File

@ -33,7 +33,6 @@ function M.run()
bit.rshift(lcg_rnd() * (disp:getHeight()-20), 8) + 20
)
tmr.wdclr()
end
print("...done")

View File

@ -1,19 +1,16 @@
-- setup SPI and connect display
function init_spi_display()
-- Hardware SPI CLK = GPIO14
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (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
-- pins can be assigned freely to available GPIOs
local sclk = 19
local mosi = 23
local cs = 22
local dc = 16
local res = 17
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
local bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
-- initialize the matching driver for your display
-- see app/include/ucg_config.h
--disp = ucg.ili9341_18x240x320_hw_spi(cs, dc, res)
disp = ucg.st7735_18x128x160_hw_spi(cs, dc, res)
--disp = ucg.ili9341_18x240x320_hw_spi(bus, cs, dc, res)
disp = ucg.st7735_18x128x160_hw_spi(bus, cs, dc, res)
end
@ -50,11 +47,6 @@ function lcg_rnd()
end
function millis()
local usec = tmr.now()
return usec/1000
end
function set_clip_range()
local x, y, w, h
w = bit.band(lcg_rnd(), 31)
@ -118,6 +110,12 @@ disp:begin(ucg.FONT_MODE_TRANSPARENT)
disp:setFont(ucg.font_ncenR14_hr)
disp:clearScreen()
milli = 0
function millis()
milli = milli + 30
return milli
end
tmr.register(0, 3000, tmr.ALARM_AUTO, function() loop() end)
tmr.start(0)
t = tmr.create()
t:register(5000, tmr.ALARM_AUTO, function() loop() end)
t:start()

View File

@ -1,15 +1,16 @@
-- setup SPI and connect display
function init_spi_display()
-- Hardware SPI CLK = GPIO14
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (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
-- pins can be assigned freely to available GPIOs
local sclk = 19
local mosi = 23
local cs = 22
local dc = 16
local res = 17
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
disp = ucg.ili9341_18x240x320_hw_spi(cs, dc, res)
local bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
--disp = ucg.ili9341_18x240x320_hw_spi(bus, cs, dc, res)
disp = ucg.st7735_18x128x160_hw_spi(bus, cs, dc, res)
end

View File

@ -1,15 +1,16 @@
-- setup SPI and connect display
function init_spi_display()
-- Hardware SPI CLK = GPIO14
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (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
-- pins can be assigned freely to available GPIOs
local sclk = 19
local mosi = 23
local cs = 22
local dc = 16
local res = 17
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
disp = ucg.st7735_18x128x160_hw_spi(cs, dc, res)
local bus = spi.master(spi.HSPI, {sclk=sclk, mosi=mosi})
--disp = ucg.ili9341_18x240x320_hw_spi(bus, cs, dc, res)
disp = ucg.st7735_18x128x160_hw_spi(bus, cs, dc, res)
end

View File

@ -52,5 +52,6 @@ pages:
- 'tmr': 'en/modules/tmr.md'
- 'u8g2': 'en/modules/u8g2.md'
- 'uart': 'en/modules/uart.md'
- 'ucg': 'en/modules/ucg.md'
- 'wifi': 'en/modules/wifi.md'
- 'ws2812': 'en/modules/ws2812.md'

54
tools/ucg_config.pl Normal file
View File

@ -0,0 +1,54 @@
#!/usr/bin/perl -w
my (@displays, @font_selection);
# scan provided header file for CONFIG_UCG_DISPLAY and CONFIG_UCG_FONT_SELECTION entries
while (<STDIN>) {
if (/^\s*#\s*define\s+CONFIG_UCG_DISPLAY_(\S+)\s+1/) {
push(@displays, lc($1));
}
if (/^\s*#\s*define\s+CONFIG_UCG_FONT_SELECTION\s+"([^"]+)"/) {
@font_selection = split(/,/, $1);
}
}
print << 'HEADER';
#ifndef _UCG_CONFIG_H
#define _UCG_CONFIG_H
HEADER
print << 'DISPLAYS';
#define UCG_DISPLAY_TABLE_ENTRY(binding, device, extension)
DISPLAYS
print("#define UCG_DISPLAY_TABLE \\\n");
foreach my $display (@displays) {
$display =~ /(\S+_\d\d)x/;
my $extension = $1;
print(" UCG_DISPLAY_TABLE_ENTRY(${display}_hw_spi, ucg_dev_${display}, ucg_ext_${extension}) \\\n");
}
print("\n");
print << 'FONTS';
#define UCG_FONT_TABLE_ENTRY(font)
#define UCG_FONT_TABLE \
FONTS
foreach my $font (@font_selection) {
print(" UCG_FONT_TABLE_ENTRY($font) \\\n");
}
print << 'FOOTER';
#endif /* _UCG_CONFIG_H */
FOOTER