From a2672113aa8d5aa1192ddc3c34cd6fb516dd0c55 Mon Sep 17 00:00:00 2001 From: devsaurus Date: Sat, 31 Jan 2015 01:21:51 +0100 Subject: [PATCH] * add u8glib * initializer for SSD1306 display with I2C driver * disabled mqtt and ow modules to avoid irom0_0_seg overflow check ld script to increase size --- app/Makefile | 3 + app/include/user_config.h | 4 +- app/modules/Makefile | 2 +- app/modules/modules.h | 4 +- app/modules/u8g.c | 195 +++++++++++++++++++++++++++++++++----- app/u8glib/Makefile | 44 +++++++++ app/u8glib/u8g.h | 8 +- app/u8glib/u8g_rot.c | 2 +- 8 files changed, 231 insertions(+), 31 deletions(-) create mode 100644 app/u8glib/Makefile diff --git a/app/Makefile b/app/Makefile index 15ff75c4..f44a96c5 100644 --- a/app/Makefile +++ b/app/Makefile @@ -31,6 +31,7 @@ SUBDIRS= \ libc \ lua \ mqtt \ + u8glib \ smart \ wofs \ modules \ @@ -77,6 +78,7 @@ COMPONENTS_eagle.app.v6 = \ libc/liblibc.a \ lua/liblua.a \ mqtt/mqtt.a \ + u8glib/u8glib.a \ smart/smart.a \ wofs/wofs.a \ spiffs/spiffs.a \ @@ -84,6 +86,7 @@ COMPONENTS_eagle.app.v6 = \ LINKFLAGS_eagle.app.v6 = \ -L../lib \ + -Xlinker -Map=mapfile \ -nostdlib \ -T$(LD_FILE) \ -Wl,--no-check-sections \ diff --git a/app/include/user_config.h b/app/include/user_config.h index 8b605dbc..00744eff 100644 --- a/app/include/user_config.h +++ b/app/include/user_config.h @@ -62,9 +62,9 @@ #define LUA_USE_MODULES_TMR #define LUA_USE_MODULES_ADC #define LUA_USE_MODULES_UART -#define LUA_USE_MODULES_OW +#undef LUA_USE_MODULES_OW #define LUA_USE_MODULES_BIT -#define LUA_USE_MODULES_MQTT +#undef LUA_USE_MODULES_MQTT #define LUA_USE_MODULES_U8G #endif /* LUA_USE_MODULES */ diff --git a/app/modules/Makefile b/app/modules/Makefile index 0198ae9c..ecb8b880 100644 --- a/app/modules/Makefile +++ b/app/modules/Makefile @@ -40,7 +40,7 @@ INCLUDES := $(INCLUDES) -I $(PDIR)include INCLUDES += -I ./ INCLUDES += -I ../libc INCLUDES += -I ../mqtt -INCLUDES += -I ../u8g +INCLUDES += -I ../u8glib INCLUDES += -I ../lua INCLUDES += -I ../platform INCLUDES += -I ../wofs diff --git a/app/modules/modules.h b/app/modules/modules.h index f4ad6b43..c37b5091 100644 --- a/app/modules/modules.h +++ b/app/modules/modules.h @@ -48,9 +48,9 @@ #if defined(LUA_USE_MODULES_U8G) #define MODULES_U8G "u8g" #define ROM_MODULES_U8G \ - _ROM(MODULES_U8G, luaopen_u8g, u8g_map) + _ROM(MODULES_U8G, luaopen_u8g, lu8g_map) #else -#define ROM_MODULES_MQTT +#define ROM_MODULES_U8G #endif #if defined(LUA_USE_MODULES_I2C) diff --git a/app/modules/u8g.c b/app/modules/u8g.c index 686d3b2c..75aeecea 100644 --- a/app/modules/u8g.c +++ b/app/modules/u8g.c @@ -7,31 +7,19 @@ #include "auxmods.h" #include "lrotable.h" -#include "c_string.h" -#include "c_stdlib.h" +//#include "c_string.h" +//#include "c_stdlib.h" -#include "c_types.h" -#include "mem.h" -#include "espconn.h" +#include "u8g.h" typedef struct lu8g_userdata { - int some_data; + uint8_t i2c_addr; + u8g_t u8g; } lu8g_userdata_t; -static int lu8g_new( lua_State *L ) -{ - lu8g_userdata_t *userdata = (lu8g_userdata_t *) lua_newuserdata( L, sizeof( lu8g_userdata_t ) ); - userdata->some_data = 100; - - // set its metatable - luaL_getmetatable(L, "u8g.display"); - lua_setmetatable(L, -2); - - return 1; -} // Lua: u8g.setup( self, id ) static int lu8g_setup( lua_State *L ) @@ -47,24 +35,183 @@ static int lu8g_setup( lua_State *L ) } + +// ------------------------------------------------------------ +// comm functions +// +#define I2C_SLA 0x3c +#define I2C_CMD_MODE 0x000 +#define I2C_DATA_MODE 0x040 + +#define ESP_I2C_ID 0 + + +static uint8_t do_i2c_start(uint8_t id, uint8_t sla) +{ + platform_i2c_send_start( id ); + + // ignore return value -> tolerate missing ACK + platform_i2c_send_address( id, sla, PLATFORM_I2C_DIRECTION_TRANSMITTER ); + + return 1; +} + +static uint8_t u8g_com_esp8266_ssd_start_sequence(u8g_t *u8g) +{ + /* are we requested to set the a0 state? */ + if ( u8g->pin_list[U8G_PI_SET_A0] == 0 ) + return 1; + + /* setup bus, might be a repeated start */ + if ( do_i2c_start( ESP_I2C_ID, I2C_SLA ) == 0 ) + return 0; + if ( u8g->pin_list[U8G_PI_A0_STATE] == 0 ) + { + // ignore return value -> tolerate missing ACK + platform_i2c_send_byte( ESP_I2C_ID, I2C_CMD_MODE ); + } + else + { + platform_i2c_send_byte( ESP_I2C_ID, I2C_DATA_MODE ); + } + + u8g->pin_list[U8G_PI_SET_A0] = 0; + 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) + { + case U8G_COM_MSG_INIT: + // we assume that the i2c bus was already initialized + //u8g_i2c_init(u8g->pin_list[U8G_PI_I2C_OPTION]); + + break; + + case U8G_COM_MSG_STOP: + break; + + case U8G_COM_MSG_RESET: + /* Currently disabled, but it could be enable. Previous restrictions have been removed */ + /* u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val); */ + break; + + case U8G_COM_MSG_CHIP_SELECT: + u8g->pin_list[U8G_PI_A0_STATE] = 0; + u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again, also forces start condition */ + if ( arg_val == 0 ) + { + /* disable chip, send stop condition */ + platform_i2c_send_stop( ESP_I2C_ID ); + } + else + { + /* enable, do nothing: any byte writing will trigger the i2c start */ + } + break; + + case U8G_COM_MSG_WRITE_BYTE: + //u8g->pin_list[U8G_PI_SET_A0] = 1; + if ( u8g_com_esp8266_ssd_start_sequence(u8g) == 0 ) + return platform_i2c_stop( ESP_I2C_ID ), 0; + if ( platform_i2c_send_byte( ESP_I2C_ID, arg_val) == 0 ) + return platform_i2c_send_stop( ESP_I2C_ID ), 0; + // platform_i2c_send_stop( ESP_I2C_ID ); + break; + + case U8G_COM_MSG_WRITE_SEQ: + //u8g->pin_list[U8G_PI_SET_A0] = 1; + if ( u8g_com_esp8266_ssd_start_sequence(u8g) == 0 ) + return platform_i2c_send_stop( ESP_I2C_ID ), 0; + { + register uint8_t *ptr = arg_ptr; + while( arg_val > 0 ) + { + // ignore return value -> tolerate missing ACK + if ( platform_i2c_send_byte( ESP_I2C_ID, *ptr++) == 0 ) + ; //return platform_i2c_send_stop( ESP_I2C_ID ), 0; + arg_val--; + } + } + // platform_i2c_send_stop( ESP_I2C_ID ); + break; + + case U8G_COM_MSG_WRITE_SEQ_P: + //u8g->pin_list[U8G_PI_SET_A0] = 1; + if ( u8g_com_esp8266_ssd_start_sequence(u8g) == 0 ) + return platform_i2c_send_stop( ESP_I2C_ID ), 0; + { + register uint8_t *ptr = arg_ptr; + while( arg_val > 0 ) + { + // ignore return value -> tolerate missing ACK + if ( platform_i2c_send_byte( ESP_I2C_ID, u8g_pgm_read(ptr) ) == 0 ) + ; //return 0; + ptr++; + arg_val--; + } + } + // platform_i2c_send_stop( ESP_I2C_ID ); + break; + + case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ + u8g->pin_list[U8G_PI_A0_STATE] = arg_val; + u8g->pin_list[U8G_PI_SET_A0] = 1; /* force a0 to set again */ + + break; + } + return 1; +} + + + + + +// device constructors + +// Lua: speed = u8g.ssd1306_128x64_i2c( i2c_addr ) +static int lu8g_ssd1306_128x64_i2c( lua_State *L ) +{ + unsigned addr = luaL_checkinteger( L, 1 ); + + if (addr == 0) + return luaL_error( L, "i2c address required" ); + + lu8g_userdata_t *userdata = (lu8g_userdata_t *) lua_newuserdata( L, sizeof( lu8g_userdata_t ) ); + + userdata->i2c_addr = (uint8_t)addr; + + u8g_InitI2C( &(userdata->u8g), &u8g_dev_ssd1306_128x64_i2c, U8G_I2C_OPT_NONE); + + + // set its metatable + luaL_getmetatable(L, "u8g.display"); + lua_setmetatable(L, -2); + + return 1; +} + + // Module function map #define MIN_OPT_LEVEL 2 #include "lrodefs.h" -static const LUA_REG_TYPE u8g_display_map[] = +static const LUA_REG_TYPE lu8g_display_map[] = { { LSTRKEY( "setup" ), LFUNCVAL( lu8g_setup ) }, #if LUA_OPTIMIZE_MEMORY > 0 - { LSTRKEY( "__index" ), LROVAL ( u8g_display_map ) }, + { LSTRKEY( "__index" ), LROVAL ( lu8g_display_map ) }, #endif { LNILKEY, LNILVAL } }; -const LUA_REG_TYPE u8g_map[] = +const LUA_REG_TYPE lu8g_map[] = { - { LSTRKEY( "new" ), LFUNCVAL ( lu8g_new ) }, + { LSTRKEY( "ssd1306_128x64_i2c" ), LFUNCVAL ( lu8g_ssd1306_128x64_i2c ) }, #if LUA_OPTIMIZE_MEMORY > 0 - { LSTRKEY( "__metatable" ), LROVAL( u8g_map ) }, + { LSTRKEY( "__metatable" ), LROVAL( lu8g_map ) }, #endif { LNILKEY, LNILVAL } }; @@ -72,11 +219,11 @@ const LUA_REG_TYPE u8g_map[] = LUALIB_API int ICACHE_FLASH_ATTR luaopen_u8g( lua_State *L ) { #if LUA_OPTIMIZE_MEMORY > 0 - luaL_rometatable(L, "u8g.display", (void *)u8g_display_map); // create metatable + luaL_rometatable(L, "u8g.display", (void *)lu8g_display_map); // create metatable return 0; #else // #if LUA_OPTIMIZE_MEMORY > 0 int n; - luaL_register( L, AUXLIB_U8G, u8g_map ); + luaL_register( L, AUXLIB_U8G, lu8g_map ); // Set it as its own metatable lua_pushvalue( L, -1 ); diff --git a/app/u8glib/Makefile b/app/u8glib/Makefile new file mode 100644 index 00000000..72a951e7 --- /dev/null +++ b/app/u8glib/Makefile @@ -0,0 +1,44 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = u8glib.a +endif + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +INCLUDES += -I ../libc +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/u8glib/u8g.h b/app/u8glib/u8g.h index afe161fc..d9ab27df 100644 --- a/app/u8glib/u8g.h +++ b/app/u8glib/u8g.h @@ -51,7 +51,7 @@ typedef signed char int8_t; typedef unsigned short uint16_t; typedef signed short int16_t; #else -#include +#include #endif #if defined(__AVR__) @@ -641,6 +641,7 @@ uint8_t u8g_com_arduino_fast_parallel_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va uint8_t u8g_com_arduino_port_d_wr_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr); /* u8g_com_arduino_port_d_wr.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_esp8266_ssd_i2c_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 */ @@ -795,6 +796,11 @@ defined(__18CXX) || defined(__PIC32MX) #endif #endif +#ifndef U8G_COM_SSD_I2C +// ESP8266 +#define U8G_COM_SSD_I2C u8g_com_esp8266_ssd_i2c_fn +#endif + #ifndef U8G_COM_SSD_I2C #define U8G_COM_SSD_I2C u8g_com_null_fn #endif diff --git a/app/u8glib/u8g_rot.c b/app/u8glib/u8g_rot.c index 3791675b..96e32c93 100644 --- a/app/u8glib/u8g_rot.c +++ b/app/u8glib/u8g_rot.c @@ -40,7 +40,7 @@ uint8_t u8g_dev_rot90_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg); uint8_t u8g_dev_rot180_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg); uint8_t u8g_dev_rot270_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg); -uint8_t u8g_dev_rot_dummy_fn(void *u8g, void *dev, uint8_t msg, void *arg) +uint8_t u8g_dev_rot_dummy_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) { return 0; }