Merge pull request #293 from devsaurus/dev

Update u8glib integration, thanks to @devsaurus
This commit is contained in:
zeroday 2015-03-18 12:46:49 +08:00
commit 1652df50cf
13 changed files with 528 additions and 105 deletions

View File

@ -364,24 +364,51 @@ The integration in nodemcu is developed for SSD1306 based display attached via t
U8glib v1.17
#####I2C connection
Hook up SDA and SCL to any free GPIOs. Eg. [lua_examples/graphics_test.lua](https://github.com/devsaurus/nodemcu-firmware/blob/dev/lua_examples/graphics_test.lua) expects SDA=5 (GPIO14) and SCL=6 (GPIO12). They are used to set up nodemcu's I2C driver before accessing the display:
Hook up SDA and SCL to any free GPIOs. Eg. `lua_examples/u8glib/graphics_test.lua` expects SDA=5 (GPIO14) and SCL=6 (GPIO12). They are used to set up nodemcu's I2C driver before accessing the display:
```lua
sda = 5
scl = 6
i2c.setup(0, sda, scl, i2c.SLOW)
```
#####SPI connection
The HSPI module is used, 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 `lua_examples/u8glib/graphics_test.lua`:
```lua
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
```
#####Library usage
The Lua bindings for this library closely follow u8glib's object oriented C++ API. Based on the u8g class, you create an object for your display type:
The Lua bindings for this library closely follow u8glib's object oriented C++ API. Based on the u8g class, you create an object for your display type.
SSD1306 via I2C:
```lua
sla = 0x3c
disp = u8g.ssd1306_128x64_i2c(sla)
```
SSD1306 via SPI:
```lua
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16, RES is optional YMMV
disp = u8g.ssd1306_128x64_spi(cs, dc, res)
```
This object provides all of u8glib's methods to control the display.
Again, refer to [lua_examples/graphics_test.lua](https://github.com/devsaurus/nodemcu-firmware/blob/dev/lua_examples/u8g_graphics_test.lua) to get an impression how this is achieved with Lua code. Visit the [u8glib homepage](https://code.google.com/p/u8glib/) for technical details.
Again, refer to `lua_examples/u8glib/graphics_test.lua` to get an impression how this is achieved with Lua code. Visit the [u8glib homepage](https://code.google.com/p/u8glib/) for technical details.
#####Fonts
u8glib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in [app/include/user_config.h](https://github.com/devsaurus/nodemcu-firmware/blob/dev/app/include/user_config.h) and recompile. Simply add the desired fonts to the font table:
u8glib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in `app/include/u8g_config.h` and recompile. Simply add the desired fonts to the font table:
```c
#define U8G_FONT_TABLE \
U8G_FONT_TABLE_ENTRY(font_6x10) \
@ -389,6 +416,9 @@ u8glib comes with a wide range of fonts for small displays. Since they need to b
```
They'll be available as `u8g.<font_name>` in Lua.
#####Bitmaps
Bitmaps and XBMs are supplied as strings to `drawBitmap()` and `drawXBM()`. This off-loads all data handling from the u8g module to generic methods for binary files. See `lua_examples/u8glib/u8g_bitmaps.lua`. Binary files can be uploaded with [nodemcu-uploader.py](https://github.com/kmpm/nodemcu-uploader).
#####Unimplemented functions
- [ ] Cursor handling
- [ ] disableCursor()
@ -397,12 +427,7 @@ They'll be available as `u8g.<font_name>` in Lua.
- [ ] setCursorFont()
- [ ] setCursorPos()
- [ ] setCursorStyle()
- [ ] Bitmaps
- [ ] drawBitmap()
- [ ] drawXBM()
- [ ] General functions
- [x] begin()
- [ ] print()
- [ ] setContrast()
- [ ] setPrintPos()
- [ ] setHardwareBackup()
@ -439,4 +464,4 @@ cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun
cc = coap.Client()
cc:get(coap.CON, "coap://192.168.18.100:5683/.well-known/core")
cc:post(coap.NON, "coap://192.168.18.100:5683/", "Hello")
```
```

21
app/include/u8g_config.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef __U8G_CONFIG_H__
#define __U8G_CONFIG_H__
// Configure U8glib fonts
// add a U8G_FONT_TABLE_ENTRY for each font you want to compile into the image
#define U8G_FONT_TABLE_ENTRY(font)
#define U8G_FONT_TABLE \
U8G_FONT_TABLE_ENTRY(font_6x10) \
U8G_FONT_TABLE_ENTRY(font_chikita)
#undef U8G_FONT_TABLE_ENTRY
// Enable display drivers
#define U8G_SSD1306_128x64_I2C
#define U8G_SSD1306_128x64_SPI
// untested
#undef U8G_PCD8544_84x48
#endif /* __U8G_CONFIG_H__ */

View File

@ -66,12 +66,4 @@
#define LED_LOW_COUNT_DEFAULT 0
#endif
// Configure U8glib fonts
// add a U8G_FONT_TABLE_ENTRY for each font you want to compile into the image
#define U8G_FONT_TABLE_ENTRY(font)
#define U8G_FONT_TABLE \
U8G_FONT_TABLE_ENTRY(font_6x10) \
U8G_FONT_TABLE_ENTRY(font_chikita)
#undef U8G_FONT_TABLE_ENTRY
#endif /* __USER_CONFIG_H__ */

View File

@ -21,6 +21,7 @@
#define LNUMKEY LRO_NUMKEY
#define LNILKEY LRO_NILKEY
#define LFUNCVAL LRO_FUNCVAL
#define LUDATA LRO_LUDATA
#define LNUMVAL LRO_NUMVAL
#define LROVAL LRO_ROVAL
#define LNILVAL LRO_NILVAL

View File

@ -11,6 +11,7 @@
/* Macros one can use to define rotable entries */
#ifndef LUA_PACK_VALUE
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
@ -18,10 +19,12 @@
#define LRO_NUMVAL(v) {.value.n = v}
#ifdef ELUA_ENDIAN_LITTLE
#define LRO_FUNCVAL(v) {{(int)v, add_sig(LUA_TLIGHTFUNCTION)}}
#define LRO_LUDATA(v) {{(int)v, add_sig(LUA_TLIGHTUSERDATA)}}
#define LRO_ROVAL(v) {{(int)v, add_sig(LUA_TROTABLE)}}
#define LRO_NILVAL {{0, add_sig(LUA_TNIL)}}
#else // #ifdef ELUA_ENDIAN_LITTLE
#define LRO_FUNCVAL(v) {{add_sig(LUA_TLIGHTFUNCTION), (int)v}}
#define LRO_LUDATA(v) {{add_sig(LUA_TLIGHTUSERDATA), (int)v}}
#define LRO_ROVAL(v) {{add_sig(LUA_TROTABLE), (int)v}}
#define LRO_NILVAL {{add_sig(LUA_TNIL), 0}}
#endif // #ifdef ELUA_ENDIAN_LITTLE

View File

@ -98,5 +98,9 @@ LUALIB_API int ( luaopen_ow )( lua_State *L );
lua_pushnumber( L, val );\
lua_setfield( L, -2, name )
#define MOD_REG_LUDATA( L, name, val )\
lua_pushlightuserdata( L, val );\
lua_setfield( L, -2, name )
#endif

View File

@ -1,6 +1,5 @@
// Module for U8glib
//#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
@ -8,25 +7,24 @@
#include "lrotable.h"
//#include "c_string.h"
//#include "c_stdlib.h"
#include "c_stdlib.h"
#include "u8g.h"
typedef u8g_t lu8g_userdata_t;
#include "u8g_config.h"
// Font look-up array
static const u8g_fntpgm_uint8_t *font_array[] =
struct _lu8g_userdata_t
{
#undef U8G_FONT_TABLE_ENTRY
#define U8G_FONT_TABLE_ENTRY(font) u8g_ ## font ,
U8G_FONT_TABLE
NULL
u8g_t u8g;
u8g_pb_t pb;
u8g_dev_t dev;
};
typedef struct _lu8g_userdata_t lu8g_userdata_t;
// shorthand macro for the u8g structure inside the userdata
#define LU8G (&(lud->u8g))
static uint32_t *u8g_pgm_cached_iadr = NULL;
static uint32_t u8g_pgm_cached_data;
// function to read 4-byte aligned from program memory AKA irom0
u8g_pgm_uint8_t ICACHE_FLASH_ATTR u8g_pgm_read(const u8g_pgm_uint8_t *adr)
@ -34,19 +32,9 @@ u8g_pgm_uint8_t ICACHE_FLASH_ATTR u8g_pgm_read(const u8g_pgm_uint8_t *adr)
uint32_t iadr = (uint32_t)adr;
// set up pointer to 4-byte aligned memory location
uint32_t *ptr = (uint32_t *)(iadr & ~0x3);
uint32_t pgm_data;
if (ptr == u8g_pgm_cached_iadr)
{
pgm_data = u8g_pgm_cached_data;
}
else
{
// read 4-byte aligned
pgm_data = *ptr;
u8g_pgm_cached_iadr = ptr;
u8g_pgm_cached_data = pgm_data;
}
// read 4-byte aligned
uint32_t pgm_data = *ptr;
// return the correct byte within the retrieved 32bit word
return pgm_data >> ((iadr % 4) * 8);
@ -79,7 +67,7 @@ static int lu8g_begin( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_Begin( lud );
u8g_Begin( LU8G );
return 0;
}
@ -92,9 +80,9 @@ static int lu8g_setFont( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_Integer fontnr = luaL_checkinteger( L, 2 );
if ((fontnr >= 0) && (fontnr < (sizeof( font_array ) / sizeof( u8g_fntpgm_uint8_t ))))
u8g_SetFont( lud, font_array[fontnr] );
u8g_fntpgm_uint8_t *font = (u8g_fntpgm_uint8_t *)lua_touserdata( L, 2 );
if (font != NULL)
u8g_SetFont( LU8G, font );
return 0;
}
@ -107,7 +95,7 @@ static int lu8g_setFontRefHeightAll( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontRefHeightAll( lud );
u8g_SetFontRefHeightAll( LU8G );
return 0;
}
@ -120,7 +108,7 @@ static int lu8g_setFontRefHeightExtendedText( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontRefHeightExtendedText( lud );
u8g_SetFontRefHeightExtendedText( LU8G );
return 0;
}
@ -133,7 +121,7 @@ static int lu8g_setFontRefHeightText( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontRefHeightText( lud );
u8g_SetFontRefHeightText( LU8G );
return 0;
}
@ -146,7 +134,7 @@ static int lu8g_setDefaultBackgroundColor( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetDefaultBackgroundColor( lud );
u8g_SetDefaultBackgroundColor( LU8G );
return 0;
}
@ -159,7 +147,7 @@ static int lu8g_setDefaultForegroundColor( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetDefaultForegroundColor( lud );
u8g_SetDefaultForegroundColor( LU8G );
return 0;
}
@ -172,7 +160,7 @@ static int lu8g_setFontPosBaseline( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontPosBaseline( lud );
u8g_SetFontPosBaseline( LU8G );
return 0;
}
@ -185,7 +173,7 @@ static int lu8g_setFontPosBottom( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontPosBottom( lud );
u8g_SetFontPosBottom( LU8G );
return 0;
}
@ -198,7 +186,7 @@ static int lu8g_setFontPosCenter( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontPosCenter( lud );
u8g_SetFontPosCenter( LU8G );
return 0;
}
@ -211,7 +199,7 @@ static int lu8g_setFontPosTop( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetFontPosTop( lud );
u8g_SetFontPosTop( LU8G );
return 0;
}
@ -224,7 +212,7 @@ static int lu8g_getFontAscent( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetFontAscent( lud ) );
lua_pushinteger( L, u8g_GetFontAscent( LU8G ) );
return 1;
}
@ -237,7 +225,7 @@ static int lu8g_getFontDescent( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetFontDescent( lud ) );
lua_pushinteger( L, u8g_GetFontDescent( LU8G ) );
return 1;
}
@ -250,7 +238,7 @@ static int lu8g_getFontLineSpacing( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetFontLineSpacing( lud ) );
lua_pushinteger( L, u8g_GetFontLineSpacing( LU8G ) );
return 1;
}
@ -263,7 +251,7 @@ static int lu8g_getMode( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetMode( lud ) );
lua_pushinteger( L, u8g_GetMode( LU8G ) );
return 1;
}
@ -276,7 +264,7 @@ static int lu8g_setColorIndex( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetColorIndex( lud, luaL_checkinteger( L, 2 ) );
u8g_SetColorIndex( LU8G, luaL_checkinteger( L, 2 ) );
return 0;
}
@ -289,7 +277,7 @@ static int lu8g_getColorIndex( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetColorIndex( lud ) );
lua_pushinteger( L, u8g_GetColorIndex( LU8G ) );
return 1;
}
@ -311,16 +299,16 @@ static int lu8g_generic_drawStr( lua_State *L, uint8_t rot )
switch (rot)
{
case 1:
lua_pushinteger( L, u8g_DrawStr90( lud, args[0], args[1], s ) );
lua_pushinteger( L, u8g_DrawStr90( LU8G, args[0], args[1], s ) );
break;
case 2:
lua_pushinteger( L, u8g_DrawStr180( lud, args[0], args[1], s ) );
lua_pushinteger( L, u8g_DrawStr180( LU8G, args[0], args[1], s ) );
break;
case 3:
lua_pushinteger( L, u8g_DrawStr270( lud, args[0], args[1], s ) );
lua_pushinteger( L, u8g_DrawStr270( LU8G, args[0], args[1], s ) );
break;
default:
lua_pushinteger( L, u8g_DrawStr( lud, args[0], args[1], s ) );
lua_pushinteger( L, u8g_DrawStr( LU8G, args[0], args[1], s ) );
break;
}
@ -371,7 +359,7 @@ static int lu8g_drawLine( lua_State *L )
u8g_uint_t args[4];
lu8g_get_int_args( L, 2, 4, args );
u8g_DrawLine( lud, args[0], args[1], args[2], args[3] );
u8g_DrawLine( LU8G, args[0], args[1], args[2], args[3] );
return 0;
}
@ -387,7 +375,7 @@ static int lu8g_drawTriangle( lua_State *L )
u8g_uint_t args[6];
lu8g_get_int_args( L, 2, 6, args );
u8g_DrawTriangle( lud, args[0], args[1], args[2], args[3], args[4], args[5] );
u8g_DrawTriangle( LU8G, args[0], args[1], args[2], args[3], args[4], args[5] );
return 0;
}
@ -403,7 +391,7 @@ static int lu8g_drawBox( lua_State *L )
u8g_uint_t args[4];
lu8g_get_int_args( L, 2, 4, args );
u8g_DrawBox( lud, args[0], args[1], args[2], args[3] );
u8g_DrawBox( LU8G, args[0], args[1], args[2], args[3] );
return 0;
}
@ -419,7 +407,7 @@ static int lu8g_drawRBox( lua_State *L )
u8g_uint_t args[5];
lu8g_get_int_args( L, 2, 5, args );
u8g_DrawRBox( lud, args[0], args[1], args[2], args[3], args[4] );
u8g_DrawRBox( LU8G, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
@ -435,7 +423,7 @@ static int lu8g_drawFrame( lua_State *L )
u8g_uint_t args[4];
lu8g_get_int_args( L, 2, 4, args );
u8g_DrawFrame( lud, args[0], args[1], args[2], args[3] );
u8g_DrawFrame( LU8G, args[0], args[1], args[2], args[3] );
return 0;
}
@ -451,7 +439,7 @@ static int lu8g_drawRFrame( lua_State *L )
u8g_uint_t args[5];
lu8g_get_int_args( L, 2, 5, args );
u8g_DrawRFrame( lud, args[0], args[1], args[2], args[3], args[4] );
u8g_DrawRFrame( LU8G, args[0], args[1], args[2], args[3], args[4] );
return 0;
}
@ -469,7 +457,7 @@ static int lu8g_drawDisc( lua_State *L )
u8g_uint_t opt = luaL_optinteger( L, (1+3) + 1, U8G_DRAW_ALL );
u8g_DrawDisc( lud, args[0], args[1], args[2], opt );
u8g_DrawDisc( LU8G, args[0], args[1], args[2], opt );
return 0;
}
@ -487,7 +475,7 @@ static int lu8g_drawCircle( lua_State *L )
u8g_uint_t opt = luaL_optinteger( L, (1+3) + 1, U8G_DRAW_ALL );
u8g_DrawCircle( lud, args[0], args[1], args[2], opt );
u8g_DrawCircle( LU8G, args[0], args[1], args[2], opt );
return 0;
}
@ -505,7 +493,7 @@ static int lu8g_drawEllipse( lua_State *L )
u8g_uint_t opt = luaL_optinteger( L, (1+4) + 1, U8G_DRAW_ALL );
u8g_DrawEllipse( lud, args[0], args[1], args[2], args[3], opt );
u8g_DrawEllipse( LU8G, args[0], args[1], args[2], args[3], opt );
return 0;
}
@ -523,7 +511,7 @@ static int lu8g_drawFilledEllipse( lua_State *L )
u8g_uint_t opt = luaL_optinteger( L, (1+4) + 1, U8G_DRAW_ALL );
u8g_DrawFilledEllipse( lud, args[0], args[1], args[2], args[3], opt );
u8g_DrawFilledEllipse( LU8G, args[0], args[1], args[2], args[3], opt );
return 0;
}
@ -539,7 +527,7 @@ static int lu8g_drawPixel( lua_State *L )
u8g_uint_t args[2];
lu8g_get_int_args( L, 2, 2, args );
u8g_DrawPixel( lud, args[0], args[1] );
u8g_DrawPixel( LU8G, args[0], args[1] );
return 0;
}
@ -555,7 +543,7 @@ static int lu8g_drawHLine( lua_State *L )
u8g_uint_t args[3];
lu8g_get_int_args( L, 2, 3, args );
u8g_DrawHLine( lud, args[0], args[1], args[2] );
u8g_DrawHLine( LU8G, args[0], args[1], args[2] );
return 0;
}
@ -571,7 +559,47 @@ static int lu8g_drawVLine( lua_State *L )
u8g_uint_t args[3];
lu8g_get_int_args( L, 2, 3, args );
u8g_DrawVLine( lud, args[0], args[1], args[2] );
u8g_DrawVLine( LU8G, args[0], args[1], args[2] );
return 0;
}
// Lua: u8g.drawXBM( self, x, y, width, height, data )
static int lu8g_drawXBM( lua_State *L )
{
lu8g_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_uint_t args[4];
lu8g_get_int_args( L, 2, 4, args );
const char *xbm_data = luaL_checkstring( L, (1+4) + 1 );
if (xbm_data == NULL)
return 0;
u8g_DrawXBM( LU8G, args[0], args[1], args[2], args[3], (const uint8_t *)xbm_data );
return 0;
}
// Lua: u8g.drawBitmap( self, x, y, count, height, data )
static int lu8g_drawBitmap( lua_State *L )
{
lu8g_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_uint_t args[4];
lu8g_get_int_args( L, 2, 4, args );
const char *bm_data = luaL_checkstring( L, (1+4) + 1 );
if (bm_data == NULL)
return 0;
u8g_DrawBitmap( LU8G, args[0], args[1], args[2], args[3], (const uint8_t *)bm_data );
return 0;
}
@ -584,7 +612,7 @@ static int lu8g_setScale2x2( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetScale2x2( lud );
u8g_SetScale2x2( LU8G );
return 0;
}
@ -597,7 +625,7 @@ static int lu8g_undoScale( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_UndoScale( lud );
u8g_UndoScale( LU8G );
return 0;
}
@ -610,7 +638,7 @@ static int lu8g_firstPage( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_FirstPage( lud );
u8g_FirstPage( LU8G );
return 0;
}
@ -623,7 +651,7 @@ static int lu8g_nextPage( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushboolean( L, u8g_NextPage( lud ) );
lua_pushboolean( L, u8g_NextPage( LU8G ) );
return 1;
}
@ -636,7 +664,7 @@ static int lu8g_sleepOn( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SleepOn( lud );
u8g_SleepOn( LU8G );
return 0;
}
@ -649,7 +677,7 @@ static int lu8g_sleepOff( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SleepOff( lud );
u8g_SleepOff( LU8G );
return 0;
}
@ -662,7 +690,7 @@ static int lu8g_setRot90( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetRot90( lud );
u8g_SetRot90( LU8G );
return 0;
}
@ -675,7 +703,7 @@ static int lu8g_setRot180( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetRot180( lud );
u8g_SetRot180( LU8G );
return 0;
}
@ -688,7 +716,7 @@ static int lu8g_setRot270( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetRot270( lud );
u8g_SetRot270( LU8G );
return 0;
}
@ -701,7 +729,7 @@ static int lu8g_undoRotation( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_UndoRotation( lud );
u8g_UndoRotation( LU8G );
return 0;
}
@ -714,7 +742,7 @@ static int lu8g_getWidth( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetWidth( lud ) );
lua_pushinteger( L, u8g_GetWidth( LU8G ) );
return 1;
}
@ -727,7 +755,7 @@ static int lu8g_getHeight( lua_State *L )
if ((lud = get_lud( L )) == NULL)
return 0;
lua_pushinteger( L, u8g_GetHeight( lud ) );
lua_pushinteger( L, u8g_GetHeight( LU8G ) );
return 1;
}
@ -776,6 +804,83 @@ static uint8_t u8g_com_esp8266_ssd_start_sequence(u8g_t *u8g)
}
static void lu8g_digital_write( u8g_t *u8g, uint8_t pin_index, uint8_t value )
{
uint8_t pin;
pin = u8g->pin_list[pin_index];
if ( pin != U8G_PIN_NONE )
platform_gpio_write( pin, value );
}
uint8_t u8g_com_esp8266_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
switch(msg)
{
case U8G_COM_MSG_STOP:
break;
case U8G_COM_MSG_INIT:
// we assume that the SPI interface was already initialized
// just care for the /CS and D/C pins
lu8g_digital_write( u8g, U8G_PI_CS, PLATFORM_GPIO_HIGH );
platform_gpio_mode( u8g->pin_list[U8G_PI_CS], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
platform_gpio_mode( u8g->pin_list[U8G_PI_A0], PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT );
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
lu8g_digital_write( u8g, U8G_PI_A0, arg_val == 0 ? PLATFORM_GPIO_LOW : PLATFORM_GPIO_HIGH );
break;
case U8G_COM_MSG_CHIP_SELECT:
if (arg_val == 0)
{
/* disable */
lu8g_digital_write( u8g, U8G_PI_CS, PLATFORM_GPIO_HIGH );
}
else
{
/* enable */
//u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW);
lu8g_digital_write( u8g, U8G_PI_CS, PLATFORM_GPIO_LOW );
}
break;
case U8G_COM_MSG_RESET:
if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE )
lu8g_digital_write( u8g, U8G_PI_RESET, arg_val == 0 ? PLATFORM_GPIO_LOW : PLATFORM_GPIO_HIGH );
break;
case U8G_COM_MSG_WRITE_BYTE:
platform_spi_send_recv( 1, arg_val );
break;
case U8G_COM_MSG_WRITE_SEQ:
{
register uint8_t *ptr = arg_ptr;
while( arg_val > 0 )
{
platform_spi_send_recv( 1, *ptr++ );
arg_val--;
}
}
break;
case U8G_COM_MSG_WRITE_SEQ_P:
{
register uint8_t *ptr = arg_ptr;
while( arg_val > 0 )
{
platform_spi_send_recv( 1, u8g_pgm_read(ptr) );
ptr++;
arg_val--;
}
}
break;
}
return 1;
}
uint8_t u8g_com_esp8266_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
{
switch(msg)
@ -865,10 +970,29 @@ uint8_t u8g_com_esp8266_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, voi
// device destructor
static int lu8g_close_display( lua_State *L )
{
lu8g_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
// free up allocated page buffer
if (lud->pb.buf != NULL)
{
c_free( lud->pb.buf );
lud->pb.buf = NULL;
}
return 0;
}
// device constructors
// Lua: speed = u8g.ssd1306_128x64_i2c( i2c_addr )
uint8_t u8g_dev_ssd1306_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg);
// Lua: object = u8g.ssd1306_128x64_i2c( i2c_addr )
static int lu8g_ssd1306_128x64_i2c( lua_State *L )
{
unsigned addr = luaL_checkinteger( L, 1 );
@ -878,9 +1002,127 @@ static int lu8g_ssd1306_128x64_i2c( lua_State *L )
lu8g_userdata_t *lud = (lu8g_userdata_t *) lua_newuserdata( L, sizeof( lu8g_userdata_t ) );
lud->i2c_addr = (uint8_t)addr;
lud->u8g.i2c_addr = (uint8_t)addr;
u8g_InitI2C( lud, &u8g_dev_ssd1306_128x64_i2c, U8G_I2C_OPT_NONE);
// Don't use the pre-defined device structure for u8g_dev_ssd1306_128x64_i2c here
// Reason: linking the pre-defined structures allocates RAM for the device/comm structure
// *before* the display is constructed (especially the page buffers)
// this consumes heap even when the device is not used at all
#if 1
// build device entry
lud->dev = (u8g_dev_t){ u8g_dev_ssd1306_128x64_fn, &(lud->pb), U8G_COM_SSD_I2C };
// populate and allocate page buffer
// constants taken from u8g_dev_ssd1306_128x64.c:
// PAGE_HEIGHT
// | Height
// | | WIDTH
// | | |
lud->pb = (u8g_pb_t){ { 8, 64, 0, 0, 0 }, 128, NULL };
//
if ((lud->pb.buf = (void *)c_zalloc(lud->pb.width)) == NULL)
return luaL_error( L, "out of memory" );
// and finally init device using specific interface init function
u8g_InitI2C( LU8G, &(lud->dev), U8G_I2C_OPT_NONE);
#else
u8g_InitI2C( LU8G, &u8g_dev_ssd1306_128x64_i2c, U8G_I2C_OPT_NONE);
#endif
// set its metatable
luaL_getmetatable(L, "u8g.display");
lua_setmetatable(L, -2);
return 1;
}
// Lua: object = u8g.ssd1306_128x64_spi( cs, dc, [res] )
static int lu8g_ssd1306_128x64_spi( lua_State *L )
{
unsigned cs = luaL_checkinteger( L, 1 );
if (cs == 0)
return luaL_error( L, "CS pin required" );
unsigned dc = luaL_checkinteger( L, 2 );
if (dc == 0)
return luaL_error( L, "D/C pin required" );
unsigned res = luaL_optinteger( L, 3, U8G_PIN_NONE );
lu8g_userdata_t *lud = (lu8g_userdata_t *) lua_newuserdata( L, sizeof( lu8g_userdata_t ) );
// Don't use the pre-defined device structure for u8g_dev_ssd1306_128x64_spi here
// Reason: linking the pre-defined structures allocates RAM for the device/comm structure
// *before* the display is constructed (especially the page buffers)
// this consumes heap even when the device is not used at all
#if 1
// build device entry
lud->dev = (u8g_dev_t){ u8g_dev_ssd1306_128x64_fn, &(lud->pb), U8G_COM_HW_SPI };
// populate and allocate page buffer
// constants taken from u8g_dev_ssd1306_128x64.c:
// PAGE_HEIGHT
// | Height
// | | WIDTH
// | | |
lud->pb = (u8g_pb_t){ { 8, 64, 0, 0, 0 }, 128, NULL };
//
if ((lud->pb.buf = (void *)c_zalloc(lud->pb.width)) == NULL)
return luaL_error( L, "out of memory" );
// and finally init device using specific interface init function
u8g_InitHWSPI( LU8G, &(lud->dev), cs, dc, res );
#else
u8g_InitHWSPI( LU8G, &u8g_dev_ssd1306_128x64_spi, cs, dc, res );
#endif
// set its metatable
luaL_getmetatable(L, "u8g.display");
lua_setmetatable(L, -2);
return 1;
}
uint8_t u8g_dev_pcd8544_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg);
// Lua: object = u8g.pcd8544_84x48( sce, dc, res )
static int lu8g_pcd8544_84x48( lua_State *L )
{
unsigned sce = luaL_checkinteger( L, 1 );
if (sce == 0)
return luaL_error( L, "SCE pin required" );
unsigned dc = luaL_checkinteger( L, 2 );
if (dc == 0)
return luaL_error( L, "D/C pin required" );
unsigned res = luaL_checkinteger( L, 3 );
if (res == 0)
return luaL_error( L, "RES pin required" );
lu8g_userdata_t *lud = (lu8g_userdata_t *) lua_newuserdata( L, sizeof( lu8g_userdata_t ) );
// Don't use the pre-defined device structure for u8g_dev_pcd8544_84x48_hw_spi here
// Reason: linking the pre-defined structures allocates RAM for the device/comm structure
// *before* the display is constructed (especially the page buffers)
// this consumes heap even when the device is not used at all
#if 1
// build device entry
lud->dev = (u8g_dev_t){ u8g_dev_pcd8544_fn, &(lud->pb), U8G_COM_HW_SPI };
// populate and allocate page buffer
// constants taken from u8g_dev_pcd8544_84x48.c:
// PAGE_HEIGHT
// | Height
// | | WIDTH
// | | |
lud->pb = (u8g_pb_t){ { 8, 48, 0, 0, 0 }, 84, NULL };
//
if ((lud->pb.buf = (void *)c_zalloc(lud->pb.width)) == NULL)
return luaL_error( L, "out of memory" );
// and finally init device using specific interface init function
u8g_InitHWSPI( LU8G, &(lud->dev), sce, dc, res );
#else
u8g_InitHWSPI( LU8G, &u8g_dev_pcd8544_84x48_hw_spi, sce, dc, res );
#endif
// set its metatable
@ -931,6 +1173,8 @@ static const LUA_REG_TYPE lu8g_display_map[] =
{ LSTRKEY( "drawPixel" ), LFUNCVAL( lu8g_drawPixel ) },
{ LSTRKEY( "drawHLine" ), LFUNCVAL( lu8g_drawHLine ) },
{ LSTRKEY( "drawVLine" ), LFUNCVAL( lu8g_drawVLine ) },
{ LSTRKEY( "drawBitmap" ), LFUNCVAL( lu8g_drawBitmap ) },
{ LSTRKEY( "drawXBM" ), LFUNCVAL( lu8g_drawXBM ) },
{ LSTRKEY( "setScale2x2" ), LFUNCVAL( lu8g_setScale2x2 ) },
{ LSTRKEY( "undoScale" ), LFUNCVAL( lu8g_undoScale ) },
{ LSTRKEY( "firstPage" ), LFUNCVAL( lu8g_firstPage ) },
@ -943,6 +1187,7 @@ static const LUA_REG_TYPE lu8g_display_map[] =
{ LSTRKEY( "undoRotation" ), LFUNCVAL( lu8g_undoRotation ) },
{ LSTRKEY( "getWidth" ), LFUNCVAL( lu8g_getWidth ) },
{ LSTRKEY( "getHeight" ), LFUNCVAL( lu8g_getHeight ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( lu8g_close_display ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "__index" ), LROVAL ( lu8g_display_map ) },
#endif
@ -951,12 +1196,21 @@ static const LUA_REG_TYPE lu8g_display_map[] =
const LUA_REG_TYPE lu8g_map[] =
{
#ifdef U8G_SSD1306_128x64_I2C
{ LSTRKEY( "ssd1306_128x64_i2c" ), LFUNCVAL ( lu8g_ssd1306_128x64_i2c ) },
#endif
#ifdef U8G_SSD1306_128x64_I2C
{ LSTRKEY( "ssd1306_128x64_spi" ), LFUNCVAL ( lu8g_ssd1306_128x64_spi ) },
#endif
#ifdef U8G_PCD8544_84x48
{ LSTRKEY( "pcd8544_84x48" ), LFUNCVAL ( lu8g_pcd8544_84x48 ) },
#endif
#if LUA_OPTIMIZE_MEMORY > 0
// Register fonts
#undef U8G_FONT_TABLE_ENTRY
#define U8G_FONT_TABLE_ENTRY(font) { LSTRKEY( #font ), LNUMVAL( __COUNTER__ ) },
#define U8G_FONT_TABLE_ENTRY(font) { LSTRKEY( #font ), LUDATA( (void *)(u8g_ ## font) ) },
U8G_FONT_TABLE
// Options for circle/ ellipse drwing
@ -992,7 +1246,7 @@ LUALIB_API int luaopen_u8g( lua_State *L )
// Register fonts
#undef U8G_FONT_TABLE_ENTRY
#define U8G_FONT_TABLE_ENTRY(font) MOD_REG_NUMBER( L, #font, __COUNTER__ );
#define U8G_FONT_TABLE_ENTRY(font) MOD_REG_LUDATA( L, #font, (void *)(u8g_ ## font) );
U8G_FONT_TABLE
// Options for circle/ ellipse drawing

View File

@ -654,6 +654,7 @@ uint8_t u8g_com_arduino_port_d_wr_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, v
uint8_t u8g_com_arduino_no_en_parallel_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); /* u8g_com_arduino_no_en_parallel.c */
uint8_t u8g_com_arduino_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); /* u8g_com_arduino_ssd_i2c.c */
uint8_t u8g_com_esp8266_ssd_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); /* u8g.c */
uint8_t u8g_com_esp8266_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); /* u8g.c */
uint8_t u8g_com_arduino_uc_i2c_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr);
uint8_t u8g_com_arduino_t6963_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); /* u8g_com_arduino_t6963.c */
@ -723,6 +724,10 @@ defined(__18CXX) || defined(__PIC32MX)
#define U8G_COM_HW_SPI u8g_com_atmega_hw_spi_fn
#define U8G_COM_ST7920_HW_SPI u8g_com_atmega_st7920_hw_spi_fn
#endif
#if defined(__XTENSA__)
#define U8G_COM_HW_SPI u8g_com_esp8266_hw_spi_fn
#define U8G_COM_ST7920_HW_SPI u8g_com_null_fn
#endif
#endif
#ifndef U8G_COM_HW_SPI
#define U8G_COM_HW_SPI u8g_com_null_fn

View File

@ -0,0 +1,84 @@
-- setup I2c and connect display
function init_i2c_display()
-- SDA and SCL can be assigned freely to available GPIOs
sda = 5 -- GPIO14
scl = 6 -- GPIO12
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)
-- CS, D/C, and RES can be assigned freely to available GPIOs
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
disp = u8g.ssd1306_128x64_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 bitmap_test(delay)
-- 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 ---")
dir = 0
next_rotation = 0
local draw_state
for draw_state = 1, 7 + 1*8, 1 do
disp:firstPage()
repeat
draw(draw_state)
until disp:nextPage() == false
tmr.delay(delay)
tmr.wdclr()
end
print("--- Bitmap Test done ---")
end
--init_i2c_display()
init_spi_display()
bitmap_test(50000)

View File

@ -1,13 +1,28 @@
-- setup I2c and connect display
function init_i2c_display()
sda = 5
scl = 6
-- SDA and SCL can be assigned freely to available GPIOs
sda = 5 -- GPIO14
scl = 6 -- GPIO12
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)
-- CS, D/C, and RES can be assigned freely to available GPIOs
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
disp = u8g.ssd1306_128x64_spi(cs, dc, res)
end
-- graphic test components
function prepare()
@ -122,9 +137,7 @@ function draw(draw_state)
end
end
function graphics_test()
init_i2c_display()
function graphics_test(delay)
print("--- Starting Graphics Test ---")
-- cycle through all components
@ -135,6 +148,7 @@ function graphics_test()
draw(draw_state)
until disp:nextPage() == false
--print(node.heap())
tmr.delay(delay)
-- re-trigger Watchdog!
tmr.wdclr()
end
@ -142,4 +156,6 @@ function graphics_test()
print("--- Graphics Test done ---")
end
graphics_test()
--init_i2c_display()
init_spi_display()
graphics_test(50000)

Binary file not shown.

View File

@ -1,13 +1,29 @@
-- setup I2c and connect display
function init_i2c_display()
sda = 5
scl = 6
-- SDA and SCL can be assigned freely to available GPIOs
sda = 5 -- GPIO14
scl = 6 -- GPIO12
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)
-- CS, D/C, and RES can be assigned freely to available GPIOs
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
disp = u8g.ssd1306_128x64_spi(cs, dc, res)
end
-- the draw() routine
function draw()
disp:setFont(u8g.font_6x10)
@ -35,13 +51,12 @@ function rotate()
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()
init_i2c_display()
print("--- Starting Rotation Test ---")
dir = 0
next_rotation = 0
@ -55,10 +70,13 @@ function rotation_test()
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.