From 89765d96790e2dc264f67592afb0e2d867b41619 Mon Sep 17 00:00:00 2001 From: Sebastien Date: Tue, 14 Jan 2020 17:34:51 -0500 Subject: [PATCH] supporting command line driven display configuration --- components/cmd_i2c/cmd_i2ctools.c | 155 +++++++++++++++++++++++++++ components/config/config.c | 37 ++++++- components/config/config.h | 2 +- components/display/display.c | 24 +++-- components/display/driver_SSD1306.c | 33 ++++-- components/services/audio_controls.c | 13 ++- 6 files changed, 241 insertions(+), 23 deletions(-) diff --git a/components/cmd_i2c/cmd_i2ctools.c b/components/cmd_i2c/cmd_i2ctools.c index 1d847628..aa64f641 100644 --- a/components/cmd_i2c/cmd_i2ctools.c +++ b/components/cmd_i2c/cmd_i2ctools.c @@ -12,6 +12,9 @@ #include "driver/i2c.h" #include "esp_console.h" #include "esp_log.h" +#include "string.h" +#include "stdio.h" +#include "config.h" #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ @@ -70,6 +73,147 @@ static struct { struct arg_end *end; } i2cconfig_args; +static struct { + struct arg_lit *clear; + struct arg_int *address; + struct arg_int *sda; + struct arg_int *scl; + struct arg_int *width; + struct arg_int *height; + struct arg_str *name; + struct arg_str *driver; + struct arg_end *end; +} i2cdisp_args; + +static struct { + struct arg_end *end; +} i2cdisp_show_args; +static int do_i2c_show_display(int argc, char **argv){ + char * config_string = (char * )config_alloc_get(NVS_TYPE_STR, "display_config") ; + if(config_string){ + ESP_LOGI(TAG,"Display configuration string is : \n" + "display_config = \"%s\"",config_string); + free(config_string); + } + else { + ESP_LOGW(TAG,"No display configuration found in nvs config display_config"); + } + return 0; +} + +static int do_i2c_set_display(int argc, char **argv) +{ + int sda = 0, scl=0, width=0, height=0, address=120; + char * name = strdup("I2S"); + char * driver= strdup("SSD136"); + char config_string[200]={}; + int nerrors = arg_parse(argc, argv, (void **)&i2cdisp_args); + if (nerrors != 0) { + arg_print_errors(stderr, i2cdisp_args.end, argv[0]); + return 0; + } + + + /* Check "--clear" option */ + if (i2cdisp_args.clear->count) { + ESP_LOGW(TAG,"Clearing display config"); + config_set_value(NVS_TYPE_STR, "display_config", ""); + } + /* Check "--address" option */ + if (i2cdisp_args.address->count) { + address=i2cdisp_args.address->ival[0]; + } + /* Check "--sda" option */ + if (i2cdisp_args.sda->count) { + sda=i2cdisp_args.sda->ival[0]; + } + else { + ESP_LOGE(TAG,"Missing parameter: --sda"); + nerrors ++; + } + /* Check "--scl" option */ + if (i2cdisp_args.scl->count) { + scl=i2cdisp_args.scl->ival[0]; + } + else { + ESP_LOGE(TAG,"Missing parameter: --scl"); + nerrors ++; + } + + /* Check "--width" option */ + if (i2cdisp_args.width->count) { + width=i2cdisp_args.width->ival[0]; + } + else { + ESP_LOGE(TAG,"Missing parameter: --width"); + nerrors ++; + } + + /* Check "--height" option */ + if (i2cdisp_args.height->count) { + height=i2cdisp_args.height->ival[0]; + } + else { + ESP_LOGE(TAG,"Missing parameter: --height"); + nerrors ++; + } + /* Check "--name" option */ + if (i2cdisp_args.name->count) { + free(name); + name=strdup(i2cdisp_args.name->sval[0]); + } + + /* Check "--name" option */ + if (i2cdisp_args.driver->count) { + free(driver); + driver=strdup(i2cdisp_args.driver->sval[0]); + } + snprintf(config_string, sizeof(config_string),"%s:scl=%i,sda=%i,width=%i,height=%i,address=%i,driver=%s",name,scl,sda,width,height,address,driver ); + free(name); + free(driver); + + if(nerrors!=0){ + return 0; + } + + ESP_LOGI(TAG,"Updating display configuration string configuration to :\n" + "display_config = \"%s\"",config_string ); + + + return config_set_value(NVS_TYPE_STR, "display_config", config_string)!=ESP_OK; +} + +static void register_i2c_set_display(){ + i2cdisp_args.address = arg_int0(NULL, "address", "", "Set the I2C bus port number (decimal format, default 120)"); + i2cdisp_args.sda = arg_int0("d", "sda", "", "Set the gpio for I2C SDA"); + i2cdisp_args.scl = arg_int0("c", "scl", "", "Set the gpio for I2C SCL"); + i2cdisp_args.width = arg_int0("w", "width", "", "Set the display width"); + i2cdisp_args.height = arg_int0("h", "height", "", "Set the display height"); + i2cdisp_args.name = arg_str0("n", "name", "", "Set the display type. Default is I2S"); + i2cdisp_args.driver = arg_str0("d", "driver", "", "Set the display driver name"); + i2cdisp_args.clear = arg_litn(NULL, "clear", 0, 1, "clear configuration"); + i2cdisp_args.end = arg_end(2); + i2cdisp_show_args.end = arg_end(1); + const esp_console_cmd_t i2c_set_display= { + .command = "set_i2c_display", + .help="Sets the i2c display options for the board", + .hint = NULL, + .func = &do_i2c_set_display, + .argtable = &i2cdisp_args + }; + const esp_console_cmd_t i2c_show_display= { + .command = "show_i2c_display", + .help="Sets the i2c display options for the board", + .hint = NULL, + .func = &do_i2c_show_display, + .argtable = &i2cdisp_show_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_set_display)); + ESP_ERROR_CHECK(esp_console_cmd_register(&i2c_show_display)); +} + + + static int do_i2cconfig_cmd(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **)&i2cconfig_args); @@ -112,6 +256,16 @@ static void register_i2cconfig(void) ESP_ERROR_CHECK(esp_console_cmd_register(&i2cconfig_cmd)); } + + + + + + + + + + static int do_i2cdetect_cmd(int argc, char **argv) { i2c_master_driver_initialize(); @@ -407,4 +561,5 @@ void register_i2ctools(void) register_i2cget(); register_i2cset(); register_i2cdump(); + register_i2c_set_display(); } diff --git a/components/config/config.c b/components/config/config.c index 0681afe2..d6187682 100644 --- a/components/config/config.c +++ b/components/config/config.c @@ -25,6 +25,7 @@ #include #include #include "esp_system.h" +#include "ctype.h" #include "esp_log.h" #include "esp_console.h" #include "esp_vfs_dev.h" @@ -89,10 +90,10 @@ static void * free_fn(void * ptr){ } #endif void init_cJSON(){ - static cJSON_Hooks hooks; // initialize cJSON hooks it uses SPIRAM memory // as opposed to IRAM #ifndef RECOVERY_APPLICATION + static cJSON_Hooks hooks; // In squeezelite mode, allocate memory from PSRAM. Otherwise allocate from internal RAM // as recovery will lock flash access when erasing FLASH or writing to OTA partition. hooks.malloc_fn=&malloc_fn; @@ -703,6 +704,39 @@ esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value){ return result; } +#define IS_ALPHA(c) isalpha((int)c) +#define TO_UPPER(c) toupper((int)c) + + + + +char * strstri (const char * str1, const char * str2){ + char *cp = (char *) str1; + char *s1, *s2; + + if ( *str2=='\0' ) + return((char *)str1); + + while (*cp){ + s1 = cp; + s2 = (char *) str2; + while ( *s1!='\0' && *s2!='\0' && (IS_ALPHA(*s1) && IS_ALPHA(*s2))?!(TO_UPPER(*s1) - TO_UPPER(*s2)):!(*s1-*s2)){ + ESP_LOGW(TAG,"Matched [%c] = [%c] ", IS_ALPHA(*s1)?TO_UPPER(*s1):*s1,IS_ALPHA(*s2)?TO_UPPER(*s2):*s2); + ++s1, ++s2; + } + + + if (*s2=='\0'){ + ESP_LOGW(TAG,"String %s found!", str2); + return(cp); + } + + ++cp; + ESP_LOGW(TAG,"%s not found. s2 is [%c]. Moving forward to %s", str2, *s2, cp); + } + ESP_LOGW(TAG,"String %s not found", str2); + return(NULL); +} IMPLEMENT_SET_DEFAULT(uint8_t,NVS_TYPE_U8); IMPLEMENT_SET_DEFAULT(int8_t,NVS_TYPE_I8); IMPLEMENT_SET_DEFAULT(uint16_t,NVS_TYPE_U16); @@ -716,3 +750,4 @@ IMPLEMENT_GET_NUM(uint16_t,NVS_TYPE_U16); IMPLEMENT_GET_NUM(int16_t,NVS_TYPE_I16); IMPLEMENT_GET_NUM(uint32_t,NVS_TYPE_U32); IMPLEMENT_GET_NUM(int32_t,NVS_TYPE_I32); + diff --git a/components/config/config.h b/components/config/config.h index f83c7276..3b4a74c7 100644 --- a/components/config/config.h +++ b/components/config/config.h @@ -37,4 +37,4 @@ void * config_alloc_get(nvs_type_t nvs_type, const char *key) ; bool wait_for_commit(); char * config_alloc_get_json(bool bFormatted); esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value); - +char * strstri (const char * str1, const char * str2); diff --git a/components/display/display.c b/components/display/display.c index 831e1d06..38228cf2 100644 --- a/components/display/display.c +++ b/components/display/display.c @@ -39,17 +39,23 @@ static bool display_handler(u8_t *data, int len); void display_init(void) { char *item = config_alloc_get(NVS_TYPE_STR, "display_config"); - if (item && *item) { - handle = &SSD1306_handle; - if (handle->init(item)) { - slimp_handler_chain = slimp_handler; - slimp_handler = display_handler; - ESP_LOGI(TAG, "Display initialization successful"); - } else { - ESP_LOGI(TAG, "Display initialization failed"); + if (item && *item) { + char * drivername=strstr(item,"driver"); + if( !drivername || (drivername && (strstr(drivername,"SSD1306") || strstr(drivername,"ssd1306")))){ + handle = &SSD1306_handle; + if (handle->init(item)) { + slimp_handler_chain = slimp_handler; + slimp_handler = display_handler; + ESP_LOGI(TAG, "Display initialization successful"); + } else { + ESP_LOGE(TAG, "Display initialization failed"); + } + }else { + ESP_LOGE(TAG,"Unknown display driver name in display config: %s",item); + } } else { - ESP_LOGI(TAG, "no display"); + ESP_LOGW(TAG, "no display"); } if (item) free(item); diff --git a/components/display/driver_SSD1306.c b/components/display/driver_SSD1306.c index cdcc72ef..4b5dc797 100644 --- a/components/display/driver_SSD1306.c +++ b/components/display/driver_SSD1306.c @@ -76,26 +76,41 @@ static bool display_init(char *config) { if (strstr(config, "I2C")) { int scl = -1, sda = -1; - int width = -1, height = -1; + int width = -1, height = -1, address=I2C_ADDRESS; char *p; - + ESP_LOGI(TAG, "Initializing I2C display with config: %s",config); // no time for smart parsing - this is for tinkerers if ((p = strcasestr(config, "scl")) != NULL) scl = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "sda")) != NULL) sda = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "width")) != NULL) width = atoi(strchr(p, '=') + 1); if ((p = strcasestr(config, "height")) != NULL) height = atoi(strchr(p, '=') + 1); + if ((p = strcasestr(config, "address")) != NULL) address = atoi(strchr(p, '=') + 1); if (sda != -1 && scl != -1 && width != -1 && height != -1) { - SSD1306_I2CMasterInitDefault( I2C_PORT, sda, scl ); - SSD1306_I2CMasterAttachDisplayDefault( &I2CDisplay, width, height, I2C_ADDRESS, -1); - SSD1306_SetFont( &I2CDisplay, &Font_droid_sans_fallback_15x17 ); - ESP_LOGI(TAG, "Initialized I2C display %dx%d (sda:%d, scl:%d)", width, height, sda, scl); - res = true; + res = SSD1306_I2CMasterInitDefault( I2C_PORT, sda, scl ); + if(!res){ + ESP_LOGE(TAG,"I2C Master Init failed"); + } + } + if(res){ + res = SSD1306_I2CMasterAttachDisplayDefault( &I2CDisplay, width, height, address, -1); + if(!res){ + ESP_LOGE(TAG,"Attach Display default failed"); + } + } + if(res){ + res = SSD1306_SetFont( &I2CDisplay, &Font_droid_sans_fallback_15x17 ); + if(!res){ + ESP_LOGE(TAG,"Set Font failed"); + } + } + if(res){ + ESP_LOGI(TAG, "Initialized I2C display %dx%d (sda:%d, scl:%d, address:%02x)", width, height, sda, scl, address); } else { - ESP_LOGI(TAG, "Cannot initialized I2C display %s [%dx%d sda:%d, scl:%d]", config, width, height, sda, scl); + ESP_LOGE(TAG, "Cannot initialized I2C display %s [%dx%d sda:%d, scl:%d, address:%02x]", config, width, height, sda, scl, address); } } else { - // other types + ESP_LOGE(TAG, "Non-I2C display not supported. Display config %s", config); } return res; diff --git a/components/services/audio_controls.c b/components/services/audio_controls.c index 5700ec54..d9e2b6b5 100644 --- a/components/services/audio_controls.c +++ b/components/services/audio_controls.c @@ -18,7 +18,7 @@ * along with this program. If not, see . * */ -//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE +#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE #include #include #include @@ -209,7 +209,7 @@ esp_err_t actrls_process_action (const cJSON * member, actrls_config_t *cur_conf esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_config) { - esp_err_t err = ESP_FAIL; + esp_err_t err = ESP_OK; const actrls_config_map_t * h=actrls_config_map; char * str = cJSON_Print(member); @@ -219,6 +219,7 @@ esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_confi ESP_LOGD(TAG,"found handler for member %s, json value %s", h->member,str?str:""); err = h->handler(member, cur_config, h->offset); } else { + err = ESP_FAIL; ESP_LOGE(TAG, "Unknown json structure member : %s", str?str:""); } @@ -227,7 +228,7 @@ esp_err_t actrls_process_member(const cJSON * member, actrls_config_t *cur_confi } esp_err_t actrls_process_button(const cJSON * button, actrls_config_t *cur_config) { - esp_err_t err= ESP_FAIL; + esp_err_t err= ESP_OK; const cJSON *member; cJSON_ArrayForEach(member, button) @@ -300,9 +301,15 @@ esp_err_t actrls_init_json(const char *config) { esp_err_t loc_err = actrls_process_button(button, cur_config); err = (err == ESP_OK) ? loc_err : err; if (loc_err == ESP_OK) { + + ESP_LOGI(TAG, "Calling button_create"); button_create((void*) cur_config, cur_config->gpio,cur_config->type, cur_config->pull,cur_config->debounce, control_handler, cur_config->long_press, cur_config->shifter_gpio); } + else{ + ESP_LOGE(TAG,"Error parsing button structure. Button will not be registered."); + } + cur_config++; } }