Commit 1652df50 authored by zeroday's avatar zeroday
Browse files

Merge pull request #293 from devsaurus/dev

Update u8glib integration, thanks to @devsaurus 
parents 51881158 b34a8b46
...@@ -364,24 +364,51 @@ The integration in nodemcu is developed for SSD1306 based display attached via t ...@@ -364,24 +364,51 @@ The integration in nodemcu is developed for SSD1306 based display attached via t
U8glib v1.17 U8glib v1.17
#####I2C connection #####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 ```lua
sda = 5 sda = 5
scl = 6 scl = 6
i2c.setup(0, sda, scl, i2c.SLOW) 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 #####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 ```lua
sla = 0x3c sla = 0x3c
disp = u8g.ssd1306_128x64_i2c(sla) 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. 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 #####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 ```c
#define U8G_FONT_TABLE \ #define U8G_FONT_TABLE \
U8G_FONT_TABLE_ENTRY(font_6x10) \ 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 ...@@ -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. 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 #####Unimplemented functions
- [ ] Cursor handling - [ ] Cursor handling
- [ ] disableCursor() - [ ] disableCursor()
...@@ -397,12 +427,7 @@ They'll be available as `u8g.<font_name>` in Lua. ...@@ -397,12 +427,7 @@ They'll be available as `u8g.<font_name>` in Lua.
- [ ] setCursorFont() - [ ] setCursorFont()
- [ ] setCursorPos() - [ ] setCursorPos()
- [ ] setCursorStyle() - [ ] setCursorStyle()
- [ ] Bitmaps
- [ ] drawBitmap()
- [ ] drawXBM()
- [ ] General functions - [ ] General functions
- [x] begin()
- [ ] print()
- [ ] setContrast() - [ ] setContrast()
- [ ] setPrintPos() - [ ] setPrintPos()
- [ ] setHardwareBackup() - [ ] setHardwareBackup()
...@@ -439,4 +464,4 @@ cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun ...@@ -439,4 +464,4 @@ cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun
cc = coap.Client() cc = coap.Client()
cc:get(coap.CON, "coap://192.168.18.100:5683/.well-known/core") cc:get(coap.CON, "coap://192.168.18.100:5683/.well-known/core")
cc:post(coap.NON, "coap://192.168.18.100:5683/", "Hello") cc:post(coap.NON, "coap://192.168.18.100:5683/", "Hello")
``` ```
\ No newline at end of file
#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__ */
...@@ -66,12 +66,4 @@ ...@@ -66,12 +66,4 @@
#define LED_LOW_COUNT_DEFAULT 0 #define LED_LOW_COUNT_DEFAULT 0
#endif #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__ */ #endif /* __USER_CONFIG_H__ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define LNUMKEY LRO_NUMKEY #define LNUMKEY LRO_NUMKEY
#define LNILKEY LRO_NILKEY #define LNILKEY LRO_NILKEY
#define LFUNCVAL LRO_FUNCVAL #define LFUNCVAL LRO_FUNCVAL
#define LUDATA LRO_LUDATA
#define LNUMVAL LRO_NUMVAL #define LNUMVAL LRO_NUMVAL
#define LROVAL LRO_ROVAL #define LROVAL LRO_ROVAL
#define LNILVAL LRO_NILVAL #define LNILVAL LRO_NILVAL
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
/* Macros one can use to define rotable entries */ /* Macros one can use to define rotable entries */
#ifndef LUA_PACK_VALUE #ifndef LUA_PACK_VALUE
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION} #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_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE} #define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL} #define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
...@@ -18,10 +19,12 @@ ...@@ -18,10 +19,12 @@
#define LRO_NUMVAL(v) {.value.n = v} #define LRO_NUMVAL(v) {.value.n = v}
#ifdef ELUA_ENDIAN_LITTLE #ifdef ELUA_ENDIAN_LITTLE
#define LRO_FUNCVAL(v) {{(int)v, add_sig(LUA_TLIGHTFUNCTION)}} #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_ROVAL(v) {{(int)v, add_sig(LUA_TROTABLE)}}
#define LRO_NILVAL {{0, add_sig(LUA_TNIL)}} #define LRO_NILVAL {{0, add_sig(LUA_TNIL)}}
#else // #ifdef ELUA_ENDIAN_LITTLE #else // #ifdef ELUA_ENDIAN_LITTLE
#define LRO_FUNCVAL(v) {{add_sig(LUA_TLIGHTFUNCTION), (int)v}} #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_ROVAL(v) {{add_sig(LUA_TROTABLE), (int)v}}
#define LRO_NILVAL {{add_sig(LUA_TNIL), 0}} #define LRO_NILVAL {{add_sig(LUA_TNIL), 0}}
#endif // #ifdef ELUA_ENDIAN_LITTLE #endif // #ifdef ELUA_ENDIAN_LITTLE
......
...@@ -98,5 +98,9 @@ LUALIB_API int ( luaopen_ow )( lua_State *L ); ...@@ -98,5 +98,9 @@ LUALIB_API int ( luaopen_ow )( lua_State *L );
lua_pushnumber( L, val );\ lua_pushnumber( L, val );\
lua_setfield( L, -2, name ) lua_setfield( L, -2, name )
#define MOD_REG_LUDATA( L, name, val )\
lua_pushlightuserdata( L, val );\
lua_setfield( L, -2, name )
#endif #endif
This diff is collapsed.
...@@ -654,6 +654,7 @@ uint8_t u8g_com_arduino_port_d_wr_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, v ...@@ -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_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_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_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_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 */ 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) ...@@ -723,6 +724,10 @@ defined(__18CXX) || defined(__PIC32MX)
#define U8G_COM_HW_SPI u8g_com_atmega_hw_spi_fn #define U8G_COM_HW_SPI u8g_com_atmega_hw_spi_fn
#define U8G_COM_ST7920_HW_SPI u8g_com_atmega_st7920_hw_spi_fn #define U8G_COM_ST7920_HW_SPI u8g_com_atmega_st7920_hw_spi_fn
#endif #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 #endif
#ifndef U8G_COM_HW_SPI #ifndef U8G_COM_HW_SPI
#define U8G_COM_HW_SPI u8g_com_null_fn #define U8G_COM_HW_SPI u8g_com_null_fn
......
-- 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)
-- setup I2c and connect display -- setup I2c and connect display
function init_i2c_display() function init_i2c_display()
sda = 5 -- SDA and SCL can be assigned freely to available GPIOs
scl = 6 sda = 5 -- GPIO14
scl = 6 -- GPIO12
sla = 0x3c sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW) i2c.setup(0, sda, scl, i2c.SLOW)
disp = u8g.ssd1306_128x64_i2c(sla) disp = u8g.ssd1306_128x64_i2c(sla)
end 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 -- graphic test components
function prepare() function prepare()
...@@ -122,9 +137,7 @@ function draw(draw_state) ...@@ -122,9 +137,7 @@ function draw(draw_state)
end end
end end
function graphics_test() function graphics_test(delay)
init_i2c_display()
print("--- Starting Graphics Test ---") print("--- Starting Graphics Test ---")
-- cycle through all components -- cycle through all components
...@@ -135,6 +148,7 @@ function graphics_test() ...@@ -135,6 +148,7 @@ function graphics_test()
draw(draw_state) draw(draw_state)
until disp:nextPage() == false until disp:nextPage() == false
--print(node.heap()) --print(node.heap())
tmr.delay(delay)
-- re-trigger Watchdog! -- re-trigger Watchdog!
tmr.wdclr() tmr.wdclr()
end end
...@@ -142,4 +156,6 @@ function graphics_test() ...@@ -142,4 +156,6 @@ function graphics_test()
print("--- Graphics Test done ---") print("--- Graphics Test done ---")
end end
graphics_test() --init_i2c_display()
init_spi_display()
graphics_test(50000)
-- setup I2c and connect display -- setup I2c and connect display
function init_i2c_display() function init_i2c_display()
sda = 5 -- SDA and SCL can be assigned freely to available GPIOs
scl = 6 sda = 5 -- GPIO14
scl = 6 -- GPIO12
sla = 0x3c sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW) i2c.setup(0, sda, scl, i2c.SLOW)
disp = u8g.ssd1306_128x64_i2c(sla) disp = u8g.ssd1306_128x64_i2c(sla)
end 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 -- the draw() routine
function draw() function draw()
disp:setFont(u8g.font_6x10) disp:setFont(u8g.font_6x10)
...@@ -35,13 +51,12 @@ function rotate() ...@@ -35,13 +51,12 @@ function rotate()
dir = dir + 1 dir = dir + 1
dir = bit.band(dir, 3) dir = bit.band(dir, 3)
-- schedule next rotation step in 1000ms
next_rotation = tmr.now() / 1000 + 1000 next_rotation = tmr.now() / 1000 + 1000
end end
end end
function rotation_test() function rotation_test()
init_i2c_display()
print("--- Starting Rotation Test ---") print("--- Starting Rotation Test ---")
dir = 0 dir = 0
next_rotation = 0 next_rotation = 0
...@@ -55,10 +70,13 @@ function rotation_test() ...@@ -55,10 +70,13 @@ function rotation_test()
draw(draw_state) draw(draw_state)
until disp:nextPage() == false until disp:nextPage() == false
tmr.delay(100000)
tmr.wdclr() tmr.wdclr()
end end
print("--- Rotation Test done ---") print("--- Rotation Test done ---")
end end
--init_i2c_display()
init_spi_display()
rotation_test() rotation_test()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment