diff --git a/app/modules/u8g.c b/app/modules/u8g.c index e882ae4e..66e75dfe 100644 --- a/app/modules/u8g.c +++ b/app/modules/u8g.c @@ -1046,6 +1046,51 @@ static int lu8g_ssd1306_128x64_i2c( lua_State *L ) return 1; } +// Lua: object = u8g.ssd1306_128x64_spi( cs, dc ) +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" ); + + lu8g_userdata_t *lud = (lu8g_userdata_t *) lua_newuserdata( L, sizeof( lu8g_userdata_t ) ); + + // We 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_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, U8G_PIN_NONE ); +#else + u8g_InitHWSPI( LU8G, &u8g_dev_ssd1306_128x64_spi, cs, dc, U8G_PIN_NONE ); +#endif + + + // set its metatable + luaL_getmetatable(L, "u8g.display"); + lua_setmetatable(L, -2); + + return 1; +} + // Module function map #define MIN_OPT_LEVEL 2 @@ -1111,6 +1156,7 @@ static const LUA_REG_TYPE lu8g_display_map[] = const LUA_REG_TYPE lu8g_map[] = { { LSTRKEY( "ssd1306_128x64_i2c" ), LFUNCVAL ( lu8g_ssd1306_128x64_i2c ) }, + { LSTRKEY( "ssd1306_128x64_spi" ), LFUNCVAL ( lu8g_ssd1306_128x64_spi ) }, #if LUA_OPTIMIZE_MEMORY > 0 // Register fonts diff --git a/lua_examples/u8g_bitmaps.lua b/lua_examples/u8g_bitmaps.lua index 0a8ac8e7..92b5f7a0 100644 --- a/lua_examples/u8g_bitmaps.lua +++ b/lua_examples/u8g_bitmaps.lua @@ -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 and D/C can be assigned freely to available GPIOs + cs = 8 -- GPIO15, pull-down 10k to GND + dc = 4 -- GPIO2 + + spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0) + disp = u8g.ssd1306_128x64_spi(cs, dc) +end + + function xbm_picture() disp:setFont(u8g.font_6x10) disp:drawStr( 0, 10, "XBM picture") @@ -34,9 +49,7 @@ function draw(draw_state) end -function bitmap_test() - init_i2c_display() - +function bitmap_test(delay) -- read XBM picture file.open("u8glib_logo.xbm", "r") xbm_data = file.read() @@ -58,10 +71,13 @@ function bitmap_test() draw(draw_state) until disp:nextPage() == false + tmr.delay(delay) tmr.wdclr() end print("--- Bitmap Test done ---") end -bitmap_test() +--init_i2c_display() +init_spi_display() +bitmap_test(50000) diff --git a/lua_examples/u8g_graphics_test.lua b/lua_examples/u8g_graphics_test.lua index edadf872..8a721e99 100644 --- a/lua_examples/u8g_graphics_test.lua +++ b/lua_examples/u8g_graphics_test.lua @@ -1,13 +1,27 @@ -- 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 and D/C can be assigned freely to available GPIOs + cs = 8 -- GPIO15, pull-down 10k to GND + dc = 4 -- GPIO2 + + spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0) + disp = u8g.ssd1306_128x64_spi(cs, dc) +end + -- graphic test components function prepare() @@ -122,9 +136,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 +147,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 +155,6 @@ function graphics_test() print("--- Graphics Test done ---") end -graphics_test() +--init_i2c_display() +init_spi_display() +graphics_test(50000) diff --git a/lua_examples/u8g_rotation.lua b/lua_examples/u8g_rotation.lua index 0d900831..5b20fca8 100644 --- a/lua_examples/u8g_rotation.lua +++ b/lua_examples/u8g_rotation.lua @@ -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 and D/C can be assigned freely to available GPIOs + cs = 8 -- GPIO15, pull-down 10k to GND + dc = 4 -- GPIO2 + + spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0) + disp = u8g.ssd1306_128x64_spi(cs, dc) +end + + -- the draw() routine function draw() disp:setFont(u8g.font_6x10) @@ -35,13 +50,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 +69,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()